前端测试框架Cypress-测试用例组织和编写

2022-07-21 14:52:56 浏览数 (1)

在深圳这个雨天!听首歌曲吧,一起阅读呢

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结构进行编写,不然在执行的时候会报错。其他的就没有什么好主意的了。和其他的测试框架也有点类似。

0 人点赞