基本使用

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

Cypress 是前端测试工具,它可以对浏览器中运行的任何内容进行快速、简单和可靠的测试,它是自集成的,提供了一套完整的端到端测试体验。无须借助其他外部工具,在简单安装后即可允许用户快速地创建、编写、运行、测试用例,并且针对每一步操作均支持回看。

原理

从技术上讲,当你运行测试时,Cypress 首先使用 webpack 将测试代码中的所有模块 bundle 到一个 js 文件中,然后,它会运行浏览器,并且将测试代码注入到一个空白页里面,然后它将在浏览器中运行测试代码(可以理解为 Cypress 通过一系列操作将测试代码放到一个 iframe 中运行)。

在每次测试首次加载 Cypress 的时,内部 Cypress Web 应用程序先把自己托管在本地的一个随机端口上(类似于 http://localhost:65874/__/),在识别出测试中发出的第一个 cy.visit() 命令后,Cypress 将会更改其本地 URL 以匹配你远程应用程序的 Origin(用于满足同源策略),这使得你的测试代码和应用程序可以在同一个 Run Loop 运行。

因为 Cypress 测试代码和应用程序均运行在由 Cypress 全权控制的浏览器中,且它们运行在同一个 Domain 下的不同 iframe 内,所以 Cypress 的测试代码可以直接操作 DOM, Window Object 设置 LocalStroage 而无需通过网络访问,这就是 Cypress 可以运行的更快的根本原因。

除此之外,Cypress 还可以在网络(请求)层进行即时读取和更改网络流量的操作。 Cypress 背后是 Node.js Process,任何发往浏览器之外的 HTTP 的请求和响应,均有 Cypress 生成的,被 Node.js Process 控制的 Proxy 进行转发。这使得 Cypress 不仅可以修改进出浏览器的所有内容,还可以更改可能影响自动化浏览器操作的代码。这使得 Cypress 相对于其他测试工具来说,不仅能从根本上控制整个自动化测试的流程,还可以提供稳定性更加可靠的结果。

使用

安装: npm install cypress --save-dev

打开: npx cypress open,或者设置脚本使用 npm run cypress

// package.json

{
  "scripts": {
    "cypress": "cypress open"
  }
}

编写一个测试用例

describe('登录', () => {
  const username = 'jack';
  const password = '123456';

  context('表单登录验证', () => {
    it('登录成功,跳转到 dashboard 页面', () => {
      cy.visit('http://localhost:7077/login');
      cy.get('input[name=username]').type(username);
      cy.get('input[name=password]').type(password);
      cy.get('form').submit();

      cy.url().should('include', '/dashboard');
      cy.get('h1').should('contain', 'jack');
    })
  })
})

开始测试,npm run cypress,单击对应的测试文件,或者点击按钮 Run all specs,Cypress 就会启动 Test Runner 运行测试。

调试测试用例

可以在 Test Runner 看到各个“时刻”的回看,包括 consoleXHR 的各种信息。

Cypress 提供了两种 debug 的方式:

第一种方法是在代码需要 debug 处,添加 cy.pause(),测试用例运行到这里将会暂停。

第二种方法是在代码需要 debug 处,添加 cy.debugcy.get('form').debug().submit()

测试框架拆解

在 Cypress 安装完成后,用 cypress open 命令首次打开 Cypress时,会自动初始化配置并生成一个默认的文件夹结构。

cypress
├── fixtures
│ └── example.json
├── integration
│ └── testLogin.js
├── plugins
│ └── index.js
├── support
│  ├── command.js 
│  └── index.js

测试夹具 Fixture

测试夹具通常配合 cy.fixture() 命令使用,主要用来存储测试用例的外部静态数据。通常存储在 .json 的后缀文件里,这部分数据通常是某个网络请求的对应响应部分,包括 HTTP 状态码和返回值。

使用测试夹具mock数据的好处有:

  • 消除了对外部功能模块的依赖。
  • 编写的测试用例可以使用测试夹具提供的固定返回值,并且你确切的知道这个返回值是你想要的
  • 因为你无须真正地发送网络请求从而使测试更快。

测试文件 integration

测试文件默认位于 cypress/integration 文件夹中,所有位于该文件夹的文件,以.js.jsx.coffeecjsxts 都将被 Cypress 视为测试文件。

插件 Plugin

用来让你可以自定义插件,以便修改或者扩展 Cypress 的内部行为,例如动态修改配置信息和环境变量等,在每个测试文件运行之前, Cypress 都会自动加载插件文件 cypress/plugin/index.js

支持文件 support

支持文件目录是放置可重用配置,例如底层通用函数或全局默认配置的绝佳地方。默认位于 cypress/support/index.js,使用支持文件非常简单,只需要在 cypress/support/index.js 文件里添加 beforeEach 函数即可。

beforeEach(() => {
  cy.log(`当前的环境变量为 ${JSON.stringify(Cypress.env())}`)
})

Cypress 配置

Cypress 的配置文件为 cypress.json

全局配置项

  • baseUrl: 默认 null,前缀的 URL,cy.visit()cy.request() 命令经常会用,它的值通常被设置为系统主域名。

  • env:默认 {},任何想用作环境变量的变量都可以设置在 env 里。

  • ignoreTestFiles:默认*.hot-update.js,忽略某些测试用例,被此选项规则匹配的测试用例不会被执行

  • numTestKeptInMemory:默认50,保留在内存的测试用例(主要是快照和命令数据)条数,此数字过大将消耗大量内存。

  • port:默认null,Cypress 占用的端口号。

  • reporter:默认 spec,在 Cypress 运行期间使用哪个 reportrt ,有 Mocha 内置的 reporter,teamcity 和 junit 等。

  • reporterOptions:默认 null,reporter 支持的选项配置。

  • testFiles: 默认 **.*.*,要加载的测试文件,可以制定具体的文件,也可以模糊匹配。

  • watchForFileChanges:默认 true,Cypress 在运行中自动检测文件变化,当有变化发生时,自动重新运行受影响的测试用例。

超时

以下配置都以毫秒为单位。

  • defaultCommandTimeout: 默认4000,命令默认超时时间。

  • execTimeou:默认60000,在 cy.exec() 命令期间,等待系统命令完成执行的超时时间。

  • taskTimeout:默认60000,在 cy.task() 命令期间,等待任务完成执行的超时时间。

  • pageLoadTimeoutpage:默认60000,等待页面加载或 cy.visit()cy.go()cy.reload() 命令触发其页面加载事件的超时时间

  • requestTimeout: 默认5000,等待 cy.wait() 命令中的 XHR 请求发出的超时时间。

  • responseTimeout: 默认30000,如下命令的超时时间,cy.request()cy.waitcy.fixturecy.getCookie()cy.getCookiescy.setCookiecy.clearCookiecy.clearCookiescy.screenshot()

文件夹/文件

  • fileSeverFolder:默认项目根目录,fileSever 目录。

  • fixturesFolder:默认cypress/fixtures,测试夹具默认文件夹。

  • integrationFolder:默认cypress/integration,测试用例默认文件夹。

  • pluginsFile:默认cypress/plugins/index.js,插件默认文件夹。

  • supportFile:默认cypress/support/index.js,支持文件默认文件夹。

  • videosFolder:默认cypress/videos,运行期间将视频保存到的文件夹的路径

  • screenshotsFolder:默认cypress/screenshots,由测试失败或者 cy.screenshot()命令引发的截图,默认文件夹所在。

可视视图

以下配置都以像素为单位;

  • viewportHeight: 默认 660,被测应用程序视图下应用程序的默认高度。

  • viewportWidth: 默认 1000,被测应用程序视图下应用程序的默认宽度。

代码中读写配置项

除了在 cypress.json 文件里更改配置项之外, Cypress 还允许我们通过 Cypress.config()去获取或覆盖某些配置项。

// 获取所有的 config 信息
Cypress.config();

// 获取指定配置项的信息
Cypress.config(name)

// 更改指定配置项的默认值
Cypress.config(name, value)

// 使用对象字面量设置多个配置项
Cypress.config(object)

重试机制

由于现代 web 应用程序几乎都是异步的,请试想一下如下情况:

  • 如果断言发生的时候应用程序尚未更新 DOM 怎么办?
  • 如果断言发生的时候应用程序正在等待其后端响应,而导致页面暂无结果怎么办?
  • 如果断言发生的时候应用程序正在进行密集计算,而导致页面未及时更新怎么办?

这些情况在现实测试用例中经常会发生,一般的处理方式是在断言前加个固定等待时间(通常硬编码,但仍有可能会发生测试失败),但 Cypress 更智能,在实际运行中,如果是断言cy.get('h1').should('contain', 'jack');,如果cy.get()命令后面的断言失败,则cy.get() 命令将重新查询应用程序的 DOM,然后 Cypress 将尝试对 cy.get() 返回的元素进行断言,如果断言仍然失败,则 cy.get() 将尝试重新查询 DOM,以此类推,直到断言成功或者 cy.get() 命令超时为止。

与其他的测试框架相比,Cypress 的这种“自动”重试能力避免了在测试代码中编写硬编码等待,使测试代码更加健壮。

多重断言

在日常测试中,有时候需要多重断言,即单个命令后跟多个断言。

cy.get('.list > li')
  .should('have.length', 2) // 第一个断言
  .and(($li) => {
    expect($li.get(0).textContent, 'first item').to.equal('选项一');
    expect($li.get(1).textContent, 'second item').to.equal('选项二');
  })

在测试过程中,如果第二个断言失败,第三个断言就永远不会执行,如果导致第二个断言失败的原因被找到且被修复了,且此时整个命令还没有超时,那么在进行第三个断言前,会再次重试第一和第二个断言。

重试的条件

Cypress 不会重试所有的命令,当命令可能改变应用程序的状态时,这些命令将不会被重试,例如 cy.click(); Cypress 仅会重试哪些查询 DOM 的命令。可以通过查看对应 API 查看是否支持重试,下面列出一些常用的可重试命令。

命令 命令 命令
.get() .last() .ParentsUntil()
.invoke() .children() .prev()
.contains() .next() .prevAll()
.find() .nextAll() .prevUntil()
.filter() .nextUntil() .focused()
.its() .not() .hash()
.eq() .parent() .closest()
.first() .parents() .document()

.first() 命令将会一直重试直到紧跟该命令后的所有断言都通过为止。

重试的超时时间是4秒,配置项为 defaultCommandTimeout。

测试报告

内置的测试报告

配置脚本:

{
  "scripts": {
    "cypress:run": "cypress run"
  }
}

1、spec格式报告

spec格式是 Mocha 的内置报告,它的输出是一个嵌套的分级视图,在 Cypress 中使用 spec 格式的报告非常简单,只需要再命令行运行时加上 --reporter=spec 即可。

npm run cypress:run -reporter=spec

会在终端界面输出 spec 格式的测试报告。

2、json格式报告

json测试报告格式将会输出一个大的 JSON 对象,同样的在命令行运行时加上 --reporter=json

npm run cypress:run -reporter=json --reporter-options "toConsole=true"

会在终端界面输出 json 格式的测试报告。

3、junit格式报告

junit 测试报告将输出一个 xml,在命令行运行时加上 --reporter=junit

npm run cypress:run -reporter=junit --reporter-options "mochaFile=results/test-output.xml,toConsole=true"

测试报告 test-output.xml 会生成在项目根目录下的 results 文件夹内,同时终端 console 上也会展示。

自定义测试报告

1、Mochawesome报告

Mochawesome 是与 JavaScript 测试框架 Mocha 一起使用的自定义报告,它运行在 Node.js >= 8 上,并与 mochawesome-report-generator 结合使用以生成独立的 HTML/CSS 报告,以帮助可视化测试运行。

安装:

npm install --save-dev mocha@5.2.0 # 指定版本, 因为6.0版本存在一个bug

npm install --save-dev mochawesome

执行命令 npm run cypress:run --reporter mochawesome

运行完成后,测试报告文件夹 mochawesome-report 会生成在项目根目录下,里面包含一个 mochawesome.html

2、用户自定义报告

(1) 在 cypress.json 文件中配置 reporter 选项,制定 reporter 文件位置。

{
  "reporter": "reporters/iTesting-custom.js"
}

(2) 编写你的自定义报告文件

// reporters/iTesting-custom.js

var mocha = require('mocha');

function MyReporter(runner) {
  mocha.reporters.Base.call(this, runner);
  var passes = 0;
  var failures = 0;

  runner.on('pass', (test) => {
    passes++;
    console.log('pass: $s', test.fullTitle());
  });

  runner.on('fail', (test, err) => {
    failures++;
    console.log('fail: $s -- error: $s', test.fullTitle(), err.message);
  });

  runner.on('end', () => {
    console.log('用户自定义报告: %d/%d', passes, passes + failures);
  });
}

module.exports = MyReporter;

(3)执行命令

npm run cypress:run --reporter ./reporters/iTesting-custom.js

测试运行结束,用户自定义的报告会显示在终端 Console 里。

生产混合测试报告

Cypress 除了支持单个测试报告,还支持混合测试报告。用户通常希望看到多个报告,比如测试在 CI 中运行时,用户既想生成 junit 格式的报告,又想在测试运行时实时看到测试输出。

Cypress 官方推荐使用 mocha-multi-reporters 来生成混合测试报告。

1、安装

npm install --save-dev mocha@5.2.0

npm install --save-dev mocha-multi-reporters

npm install --save-dev mocha-junit-reporter

2、新建文件 reporter/custom.json,并增加如下内容:

// custom.json

{
  "reporterEnable": "spec, json, mocha-junit-reporter",
  "reporterOptions": {
    "mochaFile": "cypress/resultes/iTesting-custom-[hash].xml"
  }
}

3、执行命令

npm run cypress:run --reporter mocha-junit-reporter --reporter-options configFile=./reporter/custom.json

运行完成后,测试报告文件夹 results 会生成在项目根目录下,同时 json 格式的报告也在运行中显示在 console 里。