iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
Modern Web

前端工程師在工作中的各種實戰技能 (Vue 3)系列 第 24

[Day24] Vue3 E2E Testing: Cypress 基本結構

今天這篇文章主要會介紹 Cypress 的基本結構以及常見的語法,那我們馬上開始吧!

基本結構

Cypress 的測試基本結構是由 Test Group, Test Item, Command 和 Assertion 所組成的

describe('Todo List', () => { // Test Group
  it('Does do much!', () => {  // Test Item
		expect(true).to.equal(true)  // Assertion
	})

  it('create 2 items', () => { // Test Item
    cy.visit('https://todomvc.com/examples/vue') // Command

    cy.get('.new-todo') // Command
      .type('todo A{enter}') // Command
      .type('todo B{enter}') // Command

    cy.get('.todo-list li') // Command
      .should('have.length', 2) // Assertion
  })
})

有看過我之前介紹的 Vue 3 單元測試 (Unit Testing) - Vue Test Utils + Jest 基本範例 & 核心語法 的朋友肯定會覺得 describe, it & expect 很熟悉,不過要注意的是,Cypress 並不是採用 Jest 而是 Mocha (describe & it) 和 Chai (expect)。

Test Group & Test Item

和在寫單元測試一樣,要攥寫每一筆 E2E 測試時都要以 it 為測試的最小單位,如果想要將一至多組相關聯的測試組合在一起則可以使用 describe。

https://ithelp.ithome.com.tw/upload/images/20211009/201134873Ydrmqm9cZ.png

Command

https://i.imgur.com/YiyWD9V.gif

command 是用來告訴 Cypress 要執行什麼動作的命令,我們可以透過一行一行的 command chain來讓它模擬使用者在網頁操作的行為。

it('create 2 items', () => {
  cy.visit('https://todomvc.com/examples/vue') // command

  cy.get('.new-todo') // command
    .type('todo A{enter}') // command
    .type('todo B{enter}') // command
})

這些 command 通常也很容易翻譯成人類可以讀懂的樣子

-> 瀏覽 https://todomvc.com/examples/vue 
-> 找到 class 為 .new-todo 的元素
-> 輸入完 todd A 後按下 enter
-> 輸入完 todo B 後按下 enter

Assertions

Assertions describe the desired state of your elements, your objects, and your application.

Assertions (斷言) 是用來描述了元素、物件和應用程序的期望狀態,來確保 command (命令) 的結果符合我們所預期的。

因為 Cypress 整合了很多套件,所以我們有很多種斷言的函示可以選擇,像是

又或者是 Cypress 內建的 should,should 可以傳入來自 Chai, Chai-jQuery 或 Sinon-Chai 的 Chainer,例如:

// Length
cy.get('li.selected').should('have.length', 3)

// Class
cy.get('form').find('input').should('not.have.class', 'disabled')

// Value
cy.get('textarea').should('have.value', 'foo bar baz')

// Visibility
cy.get('li').should('be.visible')
cy.get('li.hidden').should('not.be.visible')

Default Assertions

儘管 Cypress 提供了許多斷言,但有時候最好的測試可能可以沒有斷言!

it('create 2 items', () => {
  cy.visit('https://todomvc.com/examples/vue')

  cy.get('.new-todo')
    .type('todo A{enter}')
    .type('todo B{enter}')
})

什麼意思呢? 在這個例子中我們沒有寫明確的斷言,但這個測試仍然可能會以多種方式失敗,例如

  • cy.visit() 可能會無法成功的瀏覽我們的目標頁面。
  • cy.get() 可能無法在 DOM 中找到目標元素。
  • 我們想要 .type() 的輸入可能會被 disabled 無法輸入。

事實上這是因為許多命令都有一個預設內建的斷言,或者更準確的說,有一些命令可能會因為執行失敗導致測試錯誤而無需添加明顯的 (explicit) 斷言。

Automatically retry

與其他測試框架不同的是 Cypress 中有一部分的命令 (command) 會自動重試斷言直到 timeout 為止。(預設下,timeout 的長度為 4 秒)

cy.get('button').click().should('have.class', 'active')
$('button').on('click', (e) => {
  setTimeout(() => {
    $(e.target).addClass('active')
  }, 2000)
})

在上面的例子中,儘管我們在點擊 button 兩秒後才加上 active 的 class ,這條測試依然會通過。

大部分會 retry 的命令都是和 DOM 有關,例如:cy.get()、.find()、.contains() 等,你可以在 API 文件中的 ”Assertions“ 的部分來檢查這個命令是否會 retry。例如 .first()

https://ithelp.ithome.com.tw/upload/images/20211009/20113487hm4EMkAiqO.png

參考資料


今天的分享就到這邊,如果大家對我分享的內容有興趣歡迎點擊追蹤 & 訂閱系列文章,如果對內容有任何疑問,或是文章內容有錯誤,都非常歡迎留言討論或指教的!


上一篇
[Day23]Vue3 E2E Testing: Cypress 基本介紹
下一篇
[Day25] Vue3 E2E Testing: Cypress 實戰之 Todo MVC (上)
系列文
前端工程師在工作中的各種實戰技能 (Vue 3)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言