在深圳这个雨天!听首歌曲吧,一起阅读呢
1.Cypress用例组织
接着上一篇,现在来说说cypress的用例组织结构是怎样的。首先下面的代码
代码语言:javascript复制/// <reference types="cypress" />
describe("登录",function(){
const username="jane.lane"
const password="password123"
before(function(){
cy.log('所有测试用例执行前执行1次')
})
after(function(){
cy.log("所有测试用例都执行完后执行1次")
})
beforeEach(function(){
cy.log("每个测试用例前执行1次")
})
afterEach(function(){
cy.log("每个测试用例执行完成后执行1次")
})
context("HTML表单登录测试",function(){
//测试用例
it("登录成功,跳转到dashboard页",function(){
//访问刚才的登录链接
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','jane.lane')
})
it('测试1=1',function(){
expect(1).to.equal(1)
})
})
})
上面的代码就是一个测试脚本,有两个测试用例。
对于一个可执行的测试来说,必须具备
1.1、describe() -测试套件,测试套件里面可以设置context(),也可以嵌套测试套件describe(),context其实是describe()的别名
1.2、it() -代表一个测试用例,而且一个测试套件里面必须含一个测试用例it(),不然会报错
1.3、其他before(),after(),beforeEach(),afterEach(),称为钩子函数,钩子函数不能放在测试用例it()里面,这几个钩子函数相当于python-unittest的setUpClass(),setup(),teardown(),teardownClass()
1.4、describe(),context(),it(),第一个参数描述,可以随便定义,第二个参数是一个匿名函数
我们可以运行下这个脚本,可以看得出来这个两个it()测试用例执行情况,来说明钩子函数运行情况,如何运行的,请看以下运行结果
由上面运行结果可以看得出,before()在运行测试用例执行1次。after()在所有测试用例执行完成后执行1次,beforeEach()在每个测试用例执行前都执行1次,afterEach()在每个测试用例执行完成后都执行1次
所以我们编写测试用例,要按照上面的结果进行编写,钩子函数选择可以按需选择
2.测试用例可以选择性执行
在python-unittest里面测试用例的执行可以加一些装饰器,来跳过一些测试用例的执行,同样的在cypress里面同样也同样的功能,一般分为以下几种情况:
2.1、排除测试套件/测试用例-skip
代码语言:javascript复制/// <reference types="cypress" />
describe("登录",function(){
const username="jane.lane"
const password="password123"
context("HTML表单登录测试",function(){
//测试用例
it.skip("登录成功,跳转到dashboard页",function(){
//访问刚才的登录链接
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','jane.lane')
})
it('新增测试,验证before()只执行一次',function(){
expect(1).to.equal(1)
})
it('新增测试,验证beforeEach执行次数跟测试用例个数相同',function(){
expect(1).to.equal(1)
})
})
})
describe.skip('测试1=1',function(){
it('测试1=1',function(){
expect(1).to.equal(1)
})
context('排除测试套件',function(){
it('测试1!=2',function(){
expect(1).not.to.equal(2)
})
})
})
在decribe后面加skip或者在context后面加skip,就可以排除无须执行的测试用例套件,在执行用例时,不会再执行该测试套件下的测试用例
在it后面加skip,再执行测试用例,有skip的用例,执行不会再执行。
2.2、包含测试用例套件/测试用例-only
把上面的skip换成only,代码如下:
代码语言:javascript复制/// <reference types="cypress" />
describe.only("登录",function(){
const username="jane.lane"
const password="password123"
context("HTML表单登录测试",function(){
//测试用例
it("登录成功,跳转到dashboard页",function(){
//访问刚才的登录链接
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','jane.lane')
})
it('新增测试,验证before()只执行一次',function(){
expect(1).to.equal(1)
})
it('新增测试,验证beforeEach执行次数跟测试用例个数相同',function(){
expect(1).to.equal(1)
})
})
})
describe('测试1=1',function(){
it('测试1=1',function(){
expect(1).to.equal(1)
})
context('排除测试套件',function(){
it('测试1!=2',function(){
expect(1).not.to.equal(2)
})
})
被添加only的decribe(),在执行测试脚本时,只会执行第一个describe测试套件,第二不会再执行。如果在describe没有被添加only,在it被添加only同样的道理。
2.3、动态忽略测试用例
请看以下脚本的代码:
代码语言:javascript复制/// <reference types="cypress" />
describe("登录",function(){
const username="jane.lane"
const password="password123"
context('HTML表单登录测试',function(){
it('登录成功,跳转到dashboard',function(){
//如果传进来的runFlag为1,则执行
if(Cypress.env('runFlag')==1){
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','jane.lane')
}else{
this.skip()
}
})
it('测试1=1',function(){
expect(1).to.equal(1)
})
})
})
上面测试用例做了一个if-else的判断,判断runFlag是否等1来判断是否执行,怎么执行呢?
我们可以通过执行以下命令行把runFlag传进来,如下:
yarn cypress:open --env runFlag=1
第1个和第二个测试用例均被执行,运行结果如下:
如果传runFlag=0,那么只有第二个测试用例被执行,第一个测试用例被标记未执行,如下:
3.动态生成测试用例
比如我们编写测试用例时候,如果碰到多条测试用例执行步骤和检查步骤完全一样,只有输入输出不一致。我们可以通过编写一个js作为测试用例数据输入,另外一个js作为测试脚本,如下:
第一个数据数据的js文件,代码如下:
代码语言:javascript复制//导出一个数组对象,数组里面每一个对象是一组数据
export const testLoginUser=[
{
summary:"login pass",
username:"jane.lane",
password:"password123"
},
{
summary:"login fail",
username:"jane.lane",
password:"password"
}
]
第二个测试脚本的js文件,代码如下:
代码语言:javascript复制/// <reference types="cypress" />
//导入第一个数据js文件的数组对象,{testLoginUser}导入是ES6对象解构
import {testLoginUser} from './autoGenTestLogin/testLogin.data'
describe('登录',function(){
context('HTML表单登录测试',function(){
//通过for of 循环遍历数组对象数据,创建it测试用例
for(const user of testLoginUser){
it(user.summary,function(){
cy.visit('http://localhost:7077/login')
cy.get('input[name=username]').type(user.username)
cy.get('input[name=password]').type(user.password)
cy.get('form').submit()
cy.get('h1').should('contain',user.username)
})
}
})
})
最后执行结果如下:
4.总结
这次主要介绍的是测试用例组织结构、测试用例选择执行、动态生成测试用例。测试用例需要按照describe-(context)-it结构进行编写,不然在执行的时候会报错。其他的就没有什么好主意的了。和其他的测试框架也有点类似。