【cypress】3. 編寫第一個測試

把蘋果v咬哭發表於2021-05-01

當環境安裝好了之後,就可以著手嘗試第一個測試的編寫了。

一、新建一個檔案

在你的專案下的cypress/integration資料夾中建立一個新檔案sample_spec.js,我這裡直接在webstorm編輯器中建立。
建立好之後,開啟cypress的應用,會看到Cypress Test Runner立即將新檔案顯示在整合測試列表中。Cypress會監視規格
檔案的任何更改,並自動顯示任何更改。

雖然這是一個空檔案,但是也可以點選執行試試看。

顯示No tests found,這是正常情況,因為我確實啥也沒寫。不過有時候cypress在解析測試檔案內容的時候也會有這種報錯提示,
可以F12開啟開發者工具,檢視console裡是不是有錯誤訊息。

二、編寫第一個測試檔案

這裡關注點有3個:

  • 編寫第一個通過的測試。
  • 編寫我們的第一個失敗測試。
  • 觀察cypress實時網頁過載的過程

實時過載就是,當測試檔案內容有改變儲存的時候,可以看到瀏覽器自動實時過載。

1. 編寫一個測試通過的程式碼

現在,修改剛才新檔案的,新增以下程式碼,然後儲存。

describe('My First Test', () => {
    it('Does not do much!', () => {
        expect(true).to.equal(true)
    })
})

儲存後,過載執行,測試通過啦。

雖然這個測試檔案沒幹啥正經事兒,這就是第一個pass的測試!✅
在命令日誌中,有展示出的資訊,包含了測試套件、測試、以及測試斷言情況,斷言通過就是綠色的。

2. 編寫一個測試失敗的程式碼

可以在檔案裡繼續新增下面的程式碼,然後儲存。

describe('My First Test', () => {
    it('Does not do much!', () => {
        expect(true).to.equal(false)
    })
})

這時候,測試失敗了,資訊和關鍵字都是用紅色來顯示的。

3. 測試檔案中的describe, it, 和expect 是什麼

在編輯器裡檢視測試檔案,很容易看到在程式碼裡,describe, it, 和 expect這3個是關鍵字。cypress也是通過在內部
使用了其他流行的工具或者框架來實現這些功能:

  • describeit 來自於 Mocha
  • expect來自於Chai

三、編寫一個真實的測試檔案

一個完整可靠的測試通常包含3個階段:

  1. 測試前置準備
  2. 執行測試
  3. 測試執行後的斷言。

我們也會常見到一些短語概括,比如 Given, When, Then, 或者 Arrange, Act, Assert,描述的也都是這種思路。
所以,在cypress裡編寫測試檔案,同樣也遵循上述原則:

  1. 訪問一個網頁。
  2. 查詢元素。
  3. 與該元素互動。
  4. 斷言頁面上的內容。

1. 步驟一:訪問一個頁面

這裡使用官方的一個頁面作為測試頁面
將要訪問的URL傳遞給cy.visit():

describe('我的第一個測試', () => {
    it('訪問 Kitchen Sink 頁面', () => {
        cy.visit('https://example.cypress.io')
    })
})

儲存檔案後,切換到cypress執行器,可以看到如下變化:

  • 命令日誌現在顯示了新的VISIT操作。
  • 訪問的Kitchen Sink頁面已經載入到右側的預覽視窗。
  • 測試是綠色的,雖然沒有任何斷言。
    如果請求的頁面返回時帶有非2xx狀態碼,比如404或者500,或者訪問的應用程式程式碼中有JavaScript報錯,測試會失敗。
  • VISIT顯示藍色掛起狀態,直到頁面載入完成。

如果該請求返回時帶有非2xx狀態程式碼,如404或500,或者如果應用程式程式碼中有JavaScript錯誤,測試就會失敗

注意
你測試的應用程式得是你可以控制的,為什麼呢?

  • 如果你隨便測試一個別的頁面應用,它們隨時可能改變,那麼測試可能就不能順利進行。
  • 別的應用可能會進行A/B測試,那麼你多次相同的操作,可能無法獲得一致的結果。
  • 它們可能會檢測到你是一個指令碼並阻止你的訪問(谷歌會這樣做)。
  • 他們可能有安全功能啟用,防止Cypress工作。

Cypress的重點用來幫助每天構建和測試自己的應用程式的,並不是一個通用的web自動化工具,所以不適合用來測試非你控制之外的應用。

2. 步驟二:查詢一個元素

在第一步裡已經可以成功開啟測試頁面,那現在就來查詢一個元素,就拿type開刀吧。
可以使用cy.contains(),找到包含type的元素。

describe('My First Test', () => {
    it('finds the content "type"', () => {
        cy.visit('https://example.cypress.io')

        cy.contains('type')
    })
})

儲存。

這裡同樣沒加斷言,但是測試也通過了。原因在於cypress的預設斷言,許多Cypress的命令當沒有找到預期目標時候,就會構建失敗。

可以試試,用頁面上沒有的東西替換type,比如hype。測試就變紅了,但是需要4秒。為什麼要等4s,因為cypress它會自動等待並重新嘗試,不會立即失效!

3. 步驟三:點選一個元素

找到了包含type的元素,這是一個連結,於是可以點選它,在後面加上.click()即可。

describe('My First Test', () => {
  it('clicks the link "type"', () => {
    cy.visit('https://example.cypress.io')

    cy.contains('type').click()
  })
})

點選跳轉成功。

另外,從cy.contains('type').click()這行程式碼可以看出,在cypress裡可以採用鏈式呼叫的方式,更直觀的描述出要做的事情。

4. 步驟四:斷言

得到了新的頁面,就可以在新頁面里加一些斷言了,驗證跳轉成功。比如,驗證新頁面的URL是預期的URL。斷言用到.should方法。

describe('My First Test', () => {
    it('clicking "type" navigates to a new url', () => {
        cy.visit('https://example.cypress.io')

        cy.contains('type').click()

        // Should be on a new URL which includes '/commands/actions'
        cy.url().should('include', '/commands/actions')
    })
})

儲存測試檔案,測試通過,斷言正確。

新增更多的互動命令和斷言

到這裡,一個完整的測試檔案就可以說結束了。不過,cypress也並不限定在一個測試檔案裡只能做單個的互動和斷言。
因為在實際應用場景中,某些被測試的功能,可能需要多個步驟。那麼,我們可以在這個測試檔案裡繼續新增互動命令和斷言。

比如,在跳轉的新的頁面裡,可以繼續使用cy.get()來根據CSS類選擇元素。然後,可以使用.type()命令將文字輸入到選定的輸入框。
最後,我們可以驗證輸入的值是否成功。

describe('My First Test', () => {
    it('Gets, types and asserts', () => {
        cy.visit('https://example.cypress.io')

        cy.contains('type').click()

        // Should be on a new URL which includes '/commands/actions'
        cy.url().should('include', '/commands/actions')

        // Get an input, type into it and verify that the value has been updated
        cy.get('.action-email')
            .type('fake@email.com')
            .should('have.value', 'fake@email.com')
    })
})

回顧測試

最終的程式碼,就實現了在Cypress中進行一個簡短的測試:訪問一個頁面,找到並單擊一個連結,驗證URL,然後驗證新頁面上元素的行為。
如果大聲讀出來,聽起來可能是這樣的:

1. 訪問`https://example.cypress.io`
2. 找到包含了`type`的元素
3. 點選這個元素
4. 獲取新頁面的url
5. 斷言獲取到的url裡包含`/commands/actions`
6. 用css`.action-email`獲取到輸入框
7. 輸入`fake@email.com`
8. 斷言內容輸入成功

是不是符合文章開始描述的編寫測試的思想。如果用Given, When, Then來解讀也是可以的:

1. Given 一個使用者訪問`https://example.cypress.io`
2. When 他點選了type的label標籤
3. And 他在`.action-email`這個輸入框裡輸入了 "fake@email.com" 
4. Then 新頁面的url應該包含`/commands/actions`
5. And 這個`.action-email`輸入框有了輸入內容"fake@email.com" 

關於頁面轉換

上面的測試程式碼,跨越了2個頁面。
cypress會自動的發現page transition event這種頁面轉化事件,並且會自動停止執行命令,直到下一個頁面載入完成。
如果下一個頁面最終沒有載入完成,那麼Cypress就會結束測試並且標記error。

在前面提到過,Cypress在超時找到DOM元素之前等待了4秒,但是在最後的程式碼中,Cypress檢測到頁面轉換事件,它會自動將單個page LOAD事件的超時增加到60秒。
換句話說,基於命令和發生的事件,Cypress自動更改預期超時。

相關文章