Cypress实践 - 1/2

用前端语言做前端自动化开发,似乎是自然的选择,因为开源的有很多方案可供使用。 这两年最火的莫过于cypress,解决了selenium的一些痛点,官方演示也确实炫酷。

概括来讲:

  • 优势:易于调试,文档也很全
  • 劣势:只支持JavaScript,CI的录制和并行执行功能是付费功能,需要考虑在内。

cypress基础

Cypress的核心点是作为一个你每天使用的工具来构建和测试你自己的应用程序(开发或集成阶段),更多作为一个开发工具(而不是端到端测试框架).

现阶段只支持Chrome(或同内核的Edge)和Firefox

目标: 容易的能够做下面的事情,即能够编写更快,更简单和更可靠的测试

  • 设置测试环境
  • 编写测试代码
  • 执行测试
  • 调试测试

测试通常包括3个阶段: Given, When, Then

  • 设置应用程序状态.
  • 采取行动.
  • 对应用程序的状态结果做断言.

cypress 体验

# 安装
npm install cypress

# 使用
node_modules\.bin\cypress open
# 或者
./node_modules/.bin/cypress open
# 运行
cypress run

主要命令

  • visit() 访问页面 //自动等待到触发load事件
  • request() 请求API接口

执行外部命令

  • cy.task() 在Node运行命令
  • cy.exec() 执行shell命令

cy.window 可以访问应用的数据/状态

元素选择

cypress只支持CSS Selector

  • 定位元素:对于ID和class自动生成的元素,可使用data-* 定位,比如data-test,data-testid
  • Action命令支持 {force:true}
cy.get('tbody>tr').eq(0)    // Yield first 'tr' in 'tbody'
cy.get('ul>li').eq(4)       // Yield fifth 'li' in 'ul'

常用命令

  • select : 下拉列表
  • contains

等待

  • 基于DOM的命令自动重试并等待相应元素出现
  • 默认4秒超时,可以基于命令自定义超时 { timeout: 10000 }
  • visit()默认超时一分钟

执行

cypress run

  • --parallel 并行执行
  • --spec 执行某文件/文件夹 ,支持glob匹配
cypress run --headless --browser chrome
--spec "cypress/integration/myapp/**/*,cypress/integration/myapp/*"   

断言

cy.get('.datatable').find('tr').should('have.length', 4)
cy.get('.datatable').find('tr').its('length').should('be.gte', 4)
cy.get('.listings-grid')
  .find('.listing')
  .then(listing => {
    const listingCount = Cypress.$(listing).length;
    expect(listing).to.have.length(listingCount);
  });

cy.get('#mySelector').should('have.value', 'abc')

Mocha 基础测试框架

Cypress的测试部分基于最流行的基础测试框架:Mocha。

关键字

默认使用BDD样式接口

  • describe / context是别名
  • it / specify是别名
    • .only 只运行该测试,也支持 describe,context
  • beforeEach等Hooks

注:不推荐使用lambda: ()=> {}

describe('Hooks', () => {
  before(() => {
    // runs once before all tests in the block
  })

  beforeEach(() => {
    // runs before each test in the block
  })

  afterEach(() => {
    // runs after each test in the block
  })

  after(() => {
    // runs once after all tests in the block
  })
})

以上关键字对应TDD的suite/test/suiteSetup/suiteTeardown/setup/teardown

测试发现

默认匹配 “./test/*.js”, 其他用法:

mocha –recursive “./spec/*.js”

Chai 断言库

  • BDD风格(支持链式调用)
    • expect(元素,自定义错误消息): 支持第二个参数作为错误消息
    • should()
  • TDD风格(传统)
    • assert()
foo.should.be.a('string')

expect(foo).to.be.a('string')

assert.typeOf(foo, 'string')

多个验证点

.should().and()

扩展阅读

cypress

其他