Cypress 的特点
1. 基于 node.js 环境的 E2E 前端自动化测试框架
2. 支持 Chrome 和 Firefox 浏览器,自动等待
3. 不用 web driver 驱动浏览器,运行速度快
4. 支持失败用例自动截屏
5. 对运行过程的自动录制视频
6. 时光穿梭看各步骤的 snapshoot
7. 支持 CI 和并发运行,收集测试结果
8. 支持 Junit+Allure 生成测试报告
安装和使用
安装 node.js 之后,运行命令安装 cypress
$ npm install cypress --save-dev
启动待测服务 / 应用
$ npm start & wait-on http://localhost:8080
启动 Cypress Test Runner
$ npx cypress open
运行指定用例,使用 Chrome 浏览器
$ npx cypress run --spec "cypress/integration/login.js" --browser chrome
演示用例 login.js
//用例集
describe('UI loginTest',function(){
//用例
it('console root login',function(){
//打开页面
cy.visit('http://localhost:8080/rootlogin')
cy.url().should('contain','randomKey')
//输入用户,密码,点击登录
cy.get('[name=username]').type('root')
.should('have.value','root')
cy.get('[name=password]').type('password')
.should('have.value','password')
cy.get('.el-button').click()
//登录后进入页面
cy.title().should('contain','系统管理员')
cy.wait(1000)
//登出
cy.contains('root').click()
cy.contains("退出登录").click()
cy.url().should('contain','randomKey')
})
it('console user login', function(){
// user login test
})
})
元素定位方式
cy.get() - 按 CSS 或元素特定属性进行定位,累 JQuery selection
cy.contains() - 按特定字符串匹配进行元素定位
cy.xpath() - 按 XPATH 进行定位,需安装 cypress-xpath:
1) npm install cypress-xpath --save-dev
2) 在 cypress/support/index.js 中添加: require('cypress-xpath')
页面操作
HOOK 钩子示例
describe('Hooks', () => {
before(() => {
// runs once before all tests in the block
cy.log("所有的用例之前只执行一次,测试准备工作")
})
after(() => {
// runs once after all tests in the block
cy.log("所有的用例之后只执行一次")
})
beforeEach(() => {
// runs before each test in the block
cy.log("每个用例之前都会执行")
})
afterEach(() => {
// runs after each test in the block
cy.log("每个用例之后都会执行")
})
it('test case 1', () => {
cy.log("test case 1")
expect(true).to.eq(true)
})
it('test case 2', () => {
cy.log("test case 2")
expect(true).to.eq(true)
})
})
测试数据准备
describe('The Dashboard Page', () => {
beforeEach(() => {
// reset and seed the database prior to every test
// seed a user in the DB that we can control from our tests
cy.exec('npm run db:reset && npm run db:seed')
cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
.its('body')
.as('currentUser')
})
it('logs in programmatically without using the UI', function () {
// destructuring assignment of the this.currentUser object
const { username, password } = this.currentUser
// programmatically log us in without needing the UI
cy.request('POST', '/login', {
username,
password
})
// now that we're logged in, we can visit
// any kind of restricted route!
cy.visit('/dashboard')
// our auth cookie should be present
cy.getCookie('your-session-cookie').should('exist')
// UI should reflect this user being logged in
cy.get('h1').should('contain', 'jane.lane')
})
})
参数化
describe('参数化案例,输入不同的值', function() {
// 定义测试数据
var testdatas = ["北京", "上海", "南京"]
// 前置-打开浏览器
before(() => {
cy.visit('https://www.baidu.com')
})
// 参数化
testdatas.forEach((event) => {
it("百度输入框功能", function () {
cy.get('#kw').type(event)
.should('have.value', event)
.clear()
.should('have.value', '')
})
})
})
Fixture 文件读取测试数据
把账号和密码放 login.json 文件,
{
"username": "admin",
"password": "password",
"include": "/test/my/",
"text": "测试"
}
用 login.json 中的 fixture 数据登录网页
describe('登陆网站', function() {
beforeEach(() => {
cy.visit('http://ip:8080/login');
cy.fixture('login.json').as('login')
})
it("登陆案例", function (){
cy.log("读取login.json文件账号:"+this.login.username)
cy.log("读取login.json文件密码:"+this.login.password)
// let 定义变量
let username = this.login.username
let password = this.login.password
let include = this.login.include
let text = this.login.text
//输入用户名
cy.get('#account').type(username)
.should('have.value', username)
// 输入密码
cy.get('[name="password"]').type(password)
.should('have.value', password)
// 提交表单
cy.get('#submit').click()
// 判断页面跳转
cy.url().should('include', include)
cy.get('body').should('contain', text)
})
})
多个用例共享 Cookie
describe('Dashboard', () => {
before (() => {
cy.login() // log in only once before any of the tests run.
})
beforeEach (() => {
Cypress.Cookies.preserveOnce('session_id', 'remember_token')
})
it('displays stats', () => {
// ...
})
it('can do something', () => {
// ...
})
})
JUnit/Allure 产生测试报告
在 cypress.json 中添加配置, [hash] 使得每个测试集产生自己的测试结果 xml 文件(否则会被覆盖):
{
"reporter": "junit",
"reporterOptions": {
"mochaFile": "results/test_report_[hash].xml",
"toConsole": true
}
}
执行用例
$ npx cypress run
产生报告
$ allure generate ./result/ -o ./report/ --clean
关闭 Chrome 跨域检查
在 cypress.json 中加入如下配置:
{
"chromeWebSecurity": false,
}
重跑失败用例的插件
Cypress Test Runner 上单跑或跳过某个用例
https://github.com/bahmutov/cypress-skip-and-only-ui
重跑失败的用例
https://github.com/Bkucera/cypress-plugin-retries