Cypress最佳实践

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-02-26

删除等待代码

在 Cypress 中你无需使用显示等待,Cypress 的许多命令都自带 Retry(重试) 属性。在 Cypress 中,如果需要等待一个事件返回,可以使用别名,代码如下:

// 等待请求网络返回
// 错误做法 显示等待
cy.wait(500);

// 使用别名
cy.server();
cy.route('/accounts/*').as('getAccout');
cy.wait('@getAccout').then((res) => {
  cy.log(res);
})

停用条件测试

“判断一个元素是否存在,当它存在时,执行 A 操作,当它不存在时,执行B操作”,Cypress 把这种行为称为条件测试,并认为条件测试是导致测试不稳定的根本原因,因为当你在代码中进行如此判断时,就说明你无法确定你的操作会导致哪种结果发生(而这显然是有风险的,例如执行A操作的代码有误,但A操作却一直没有满足条件而触发,则A操作测试的问题将无法被测到)

Cypress 建议你通过指定前置测试条件来避免操作引发的不确定行为,例如,当有A、B策略的需求时,指定测试前置条件使得A或B一定发生。比如 before 钩子。

测试调试

使用 .debug 命令

cy.get('#login').debug().should('have.attr', 'href');

cy.debug();

使用 debugger

it('调试', () => {
  cy.visit('/main');

  debugger; // 不工作
  // 因为Cypress命令是异步的关系,当执行cy.visit() 的时候,Cypress并没有立刻运行你的测试

  cy.get('#login').then(($el) => {
    // 可以正常调试 
    // 在.then()命令已经执行完成 查找元素存在重试 所以不能直接debugger 需要在 .then() 里面
    debugger
  })

  cy.pause(); // 暂停
})

运行时的截图和录屏

当你以 cypress run 方式(无头)运行测试时,当你的测试发生错误时,Cypress会自动截图,并默认保存在 cypress/screenshots 文件夹下。

你也可以在代码里自定义截图,无论测试失败与否。

// 直接截图
cy.screenshot();

// 只截某个特定的元素
cy.get('#login').screenshot();

所支持的语法如下:

.screenshot()
.screenshot(fileName)
.screenshot(options)
.screenshot(fileName, options)

fileName 是待保存图片的名称,可以在 cypress.json 配置 screenshotsFolder 来修改此路径,options 支持的选项如下:

  • log: 默认true,在命令中显示。

  • blackout: 默认[],此参数接受一个数组类型的字符选择器,此选择器匹配的元素会被涂黑,这个选项在 capture 为 runner 时不起作用。

  • capture:默认'fullPage',决定截图测试运行器哪个部分,此参数在元素截图时不起作用。

    • fullPage: 整个被测程序界面都会被截图
    • runner:截图包括测试运行器的整个部分
    • viewport:截图大小是被测程序的当前视窗大小
    • 对于在测试失败时自动花去的截图,此选项强制设置为 runner
  • clip: 默认null,用于裁剪最终屏幕截图图像的位置和尺寸。 { clip: { x: 0, y: 0, width: 100, height: 100} }

  • disableTimersAndAnimations:默认true,为true时则在截屏时进制 JavaScript 计时器和 CSS 动画进行。

  • padding:默认null,用于更改元素屏幕截图尺寸的填充,{ padding: ['background-color: #f7f750;'] } / { padding: 10 }

  • scale:默认false,是否缩放应用程序以适合浏览器饰扣,当 capture 为 runner 时,强制为 true。

  • timeout:默认reponseTimeout,超时时间。

  • onBeforeScreenshot:默认null,主动截图时要执行的回调函数,当用于元素屏幕截图时,参数为被截取的元素,当应用于其他截图时,参数为 document 本身。

  • onAfterScreenshot:默认null,主动截图后要执行的回调函数,第一个参数与onBeforeScreenshot一样,第二个参数是有关屏幕截图的属性。

示例:

let screenshots = [];

cy.get('input[name=password]').screenshot({
  onBeforeScreenshot($el) {
    screenshots.push($el)
  }
})
cy.log(screenshots);

cy.get('input[name=password]').screenshot({
  onAfterScreenshot($el, props) {
    screenshots.push(props)
  }
})
cy.log(screenshots);

断言最佳实践

Cypress 的断言基于当下流行的 Chai 断言库,并且增加了对 Sinon-Chai,Chai-jQuery 断言库的支持,带了强大的断言功能,支持 BDD(expect/should) 和 TDD(assert) 格式的断言。

Cypress 具有内置的断言,这些断言将导致命令主动重试,以确保命令成功(或者超时失败)。比如 cy.visit() / cy.request() / cy.contains() / cy.get() / cy.type() / cy.click() / cy.its()

还提供了两个方法来断言:

  • 隐性断言 .should().and()cy.get('#header').should('have.class', 'active').and('have.attr', 'href', '/users')
  • 显示断言 expect():允许你传入一个特定的对象并且对它进行断言,例如 expect(true).to.be.true;

还可以混合使用:

cy.get('tbody tr:first').should(($tr) => {
  expect($tr).to.have.class('active');
  expect($tr).to.have.attr('href', '/users');
})