[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

参考资料


今天的分享就到这边,如果大家对我分享的内容有兴趣欢迎点击追踪 & 订阅系列文章,如果对内容有任何疑问,或是文章内容有错误,都非常欢迎留言讨论或指教的!


<<:  [Day24] Marketplace

>>:  Day27

[Day 4] Course 1_Foundation - 分析思维(Thinking analytically)

《30天带你上完 Google Data Analytics Certificate 课程》系列将...

day17 不懂kotlin flow资料流? 那喝杯进口奶茶吧

用过Rx或reactive stream的大大,应该会很好理解flow,从设计概念来讲,flow也属...

[Day20] Google Map 评论爬虫详细教学

前一篇有提到url的连结不是Google店家页面的连结,需要透过Chrome的开发者工具才能找到~ ...

Day 28 | 很像 Vue 的 AlpineJS(三): x-model

昨天还少讲了一个最最最常用到的 x-model。如同他的样子,跟 v-model、wire:mode...

Day 1 行前说明

领队报告领队报告,Python爬虫之旅就要启程啦~ 请团员们准备好行李,我们准备出发! 今天的影片为...