专栏文章 前端自动化测试工具 Cypress 试用调研记录

Jerry li · May 06, 2019 · Last by pythonCN replied at August 27, 2019 · 9475 hits
本帖已被设为精华帖!

前言

前段时间在论坛看到cypress 的介绍,正好想了解一下前端测试框架,所以使用和调研了一下。以下是相关记录。
参考官网: https://www.cypress.io/

环境准备

1.工具:vs code;环境:node.js。

按网上教程安装即可。

2.安装 cypress

cd /your/project/path
npm install cypress --save-dev

3.安装插件:

npm install eslint-plugin-cypress --save-dev
npm install --save-dev eslint-plugin-chai-friendly

##4.配置:
在根目录下创建package.json:

{
"scripts": {
"cypress:open": "cypress open"
},
"devDependencies": {
"eslint-plugin-chai-friendly": "^0.4.1",
"eslint-plugin-cypress": "^2.2.1"
}
}

在 // my-project/cypress/ 目录下创建 .eslintrc.json:

{
"plugins": [
"cypress",
"chai-friendly"
],
"rules": {
"no-unused-expressions": 0,
"chai-friendly/no-unused-expressions": 2
},
"env": {
"cypress/globals": true
},

"extends": [
"plugin:cypress/recommended"
]

}

5.启动命令:

npm run cypress:open

helloworld:

your-project/cypress/intgration 目录下新建 sample-spec.js

describe('My first test case for cypress',function(){
it('Does not match!',function(){
expect(true).to.equal(true)
})
})

在 cypress 窗口点击当前用例执行:

注意在编写用例时,每次保存会自动触发测试,对于调试来说是比较方便的。

第一个用例

访问百度首页并搜索 testerhome:

describe('My first test case for cypress',function(){
it('visit baidu home page and search for testerhome:',function(){
cy.visit('http://www.baidu.com') //访问url
cy.title().should('contain','百度一下,你就知道') //验证页面 title 是否正确
cy.get('#kw') //根据 css 定位搜索输入框
.type('testerhome') //输入关键字
.should('have.value','testerhome') //验证关键字自动是否展示正确
cy.get('#su').click() //根据 css 定位搜索按钮并点击
cy.url().should('include','wd=testerhome') //验证目标url 是否正确包含关键字
cy.title().should('contain','testerhome_百度搜索') //验证页面 title 是否正确
cy.get('[id="1"]')
.should('contain','TesterHome') // 验证第一个结果中是否包含TesterHome
cy.screenshot()
})
})

生成的截图:

这里有一个比较特别的 snapshot 功能,可以记录下执行过程中的每一步,并可以查看当时的页面(真实的网页,不是图片)

元素定位方式

  • get:按 css 或元素特定属性的方式定位元素
  • contains:按特定字符串定位元素

使用request 请求进行登录

cypress 推荐在每个用例的登录步骤,不调用 UI ,直接使用 request 登录。下面是一个例子:

describe('My first test case for cypress',function(){
it('login as admin without UI:',function(){
const accountTypes = { // 设置账号类型
admin:{
account:'admin',
password:'123456'
}
}

cy.request({
url:'http://yourhost/login',
method:'POST',
form:true,
body:accountTypes['admin'] // 使用 admin 账号登录(跳过 UI 的登录)
})
cy.visit('/profile')
cy.url().should('include','profile') //验证目标url 是否正确
cy.get('#headerTitle')
.should('have.text','个人信息') // 验证是否包含标题 个人信息,
})
})

提取登录方法为公共方法

Cypress.Commands.add('login', (userType, options = {}) => {
const accountTypes = { // 设置账号类型
admin:{
account:'admin',
password:'123456'
}
}

cy.request({
url:'http://yourhost/login',
method:'POST',
form:true,
body:accountTypes[userType] // 使用 admin 账号登录
})
})

describe('login with different account',function(){
beforeEach(function() {
cy.login('admin')
cy.visit('/')
})

it('进入商品列表页面',function(){

cy.contains('商品列表').click()
cy.get('#headerTitle')
.should('have.text','商品列表') // 验证是否包含标题 商品列表
})

it('进入订单列表页面',function(){
cy.contains('订单列表').click()
cy.get('#headerTitle')
.should('have.text','订单列表') // 验证是否包含标题 订单列表
})
})

命令行执行所有用例

npm run cypress:run

具体运行参数可以在 package.json 下配置:

"scripts": {
"cypress:run": "cypress run --browser chrome"
}

解决chrome 下的跨域问题:

在 cypress.json 中添加:

"chromeWebSecurity": false

生成Junit-allure报表

在 cypress.json 中添加依赖:

"reporter": "junit",
"reporterOptions": {
"mochaFile": "results/my-test-output[hash].xml", // 通过hash 标签区分不同文件的用例结果
"toConsole": true
}

执行 cypress run 的时候会自动生成xml文件
使用 allure 生成对应报告:

// 生成allure 报告
allure generate results --clean

// 打开报告
allure open allure-report

生成 mocha awsome 报告

安装对应模块:
注意: mocha 必须指定 5.2.0, 否则会报错

npm install --save-dev mocha@5.2.0 mochawesome mochawesome-merge mochawesome-report-generator

配置cypress 对应报告信息 cypress.json:

"reporter": "mochawesome",
"reporterOptions": {
"overwrite": false,
"html": false,
"json": true
},

编写执行测试和生成报告的脚本:
scripts\cypress.js

const cypress = require('cypress')
const fse = require('fs-extra')
const { merge } = require('mochawesome-merge')
const generator = require('mochawesome-report-generator')

async function runTests() {
await fse.remove('mochawesome-report')
const { totalFailed } = await cypress.run()
const jsonReport = await merge()
await generator.create(jsonReport)
process.exit(totalFailed)
}

runTests()

在 package.json 文件添加对应启动脚本:

"scripts": {
"cypress:open": "cypress open",
"cy:run": "node scripts/cypress.js"
}

启动执行:

npm run cy:run

查看报告:
mochawesome-report\mochawesome.html

总结

优点:

  • 速度感觉上比selenium 要快。
  • 内置的request 方法可以直接跳过UI 层的登录,但要求是你能调用对应的登录接口。
  • 某些步骤运行失败时自动重试。这样可以提高运行的稳定性。
  • 运行失败时自动截图。

待研究:

  • 可以使用allure 或 mochawesome 生成报告, 但如何在报告里附上截图? 暂时没找到好的方法解决。
  • 与jenkins 的集成: 尝试使用docker 来执行用例并生成报告,但目前卡在无法获取到docker中任务完成的退出节点。
  • 用例能否并发运行?
共收到 15 条回复 时间 点赞

正好前一阵也在看,速度确实比selenium快很多,国内不知道用的人多不多,目前感觉文档都是官方文档,看起来头大,目前还没有头绪,只能简单的进行一下尝试

Jerry li #2 · May 06, 2019 作者
riklu 回复

社区里有相关的帖子介绍和群,有兴趣可以找来看一下
我也是看的官方文档,有些问题例如报告里怎么插入截图、如何并发执行等问题还没找到答案

解决chrome 下的跨域问题:
在 cypress.json 中添加:

请问这里的跨域问题该怎么理解啊?有例子么,什么时候会出现这种跨域的情况呢?
我是纯测试选手,对前端知识了解的不深。

Jerry li #4 · May 07, 2019 作者
zhang 回复

名词解释(网上找的):

跨域:

浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cnb.cn是不同域),所以跨域就出现了.

举个例子,某个网页的域名是 a.test.com, 如果网页上有一个js 是请求的 b.test.com 的, 就是属于跨域了,如果没有设置同源策略,请求就会失败。

下面是 cypress 官网中关于这部分的解释:

Because Cypress works from within the browser, Cypress must be able to directly communicate with your remote application at all times. Unfortunately, browsers naturally try to prevent Cypress from doing this.

我的理解是cypress 的运行机制导致在访问被测系统时,某些情况下会产生跨域的报错,因此需要通过这个设置项来避免此类问题。

思寒_seveniruby 将本帖设为了精华贴 07 May 13:29

绕过了webdriver的协议,直接用js操作的确更方便更快的。适合前端研发自己搞测试。跨域的问题可以通过nginx反向代理解决。

为啥我这边涉及到验证页面title的都会报错走不下去,我把那段代码注释掉就正常了超时时间设置了10000都不行

Jerry li #8 · May 14, 2019 作者
迷惘 回复

你这是有乱码了, 验证不通过啊 看截图: 百度一下,你就知道 里面 不包含 XXX (一串乱码)

Jerry li 回复

😰 好吧 编码格式没转过来....

cypress能够使用python进行兼容吗?比如python主流的测试框架+cypress

快出Python版本了

Author only

那到时候值得研究一下了,应该能实现低耦合框架

必须要使用js语言?可以使用其他语言来编写吗

Jerry li #15 · August 19, 2019 作者
pythonCN 回复

好像可以调用Python脚本来执行。
论坛里有个群组是关于这个框架的,你可以在论坛搜一下

Jerry li 回复

🍻 好的

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up