测试用例的组织和编写
学会了Cypress的基础操作和框架结构,这一章咱们来聊聊怎么把测试用例写得更规范、更好维护。就像写文章要分段落、列提纲,测试用例也需要清晰的结构,才能让人一看就懂,改起来也方便。
一、认识Mocha:Cypress的"骨架"
Cypress底层用了Mocha测试框架,咱们写的测试用例都是基于它的语法。简单说,Mocha就像一套"写作模板",规定了用例该怎么分组、怎么描述步骤。
最核心的两个语法:
describe()
:用来分组,比如"登录功能""购物车功能",可以嵌套,方便按模块组织用例。it()
:描述具体的测试场景,比如"输入正确账号密码能登录""密码错误时提示错误信息"。
举个例子,登录功能的用例结构可以这样写:
javascript
// 分组:登录功能
describe('登录功能', function() {
// 场景1:正确输入登录成功
it('输入正确账号密码,应该跳转到首页', function() {
// 测试步骤...
})
// 场景2:密码错误提示错误
it('密码错误时,应该显示"密码错误"提示', function() {
// 测试步骤...
})
})
二、钩子函数:用例的"前置准备"和"事后清理"
写测试时,经常需要在每个用例前做相同的准备(比如打开登录页),或用例后做清理(比如退出登录)。Mocha的钩子函数能帮你自动完成这些操作,不用重复写代码:
before()
:在整个分组(describe)的所有用例运行前执行一次,比如初始化测试数据。after()
:在整个分组的所有用例运行后执行一次,比如清理测试数据。beforeEach()
:每个用例(it)运行前都执行,比如每次测试前都打开登录页。afterEach()
:每个用例运行后都执行,比如每次测试后都清空输入框。
举个例子,登录测试前自动打开登录页:
javascript
describe('登录功能', function() {
// 每个用例运行前都访问登录页
beforeEach(function() {
cy.visit('/login')
})
it('正确输入登录成功', function() {
// 这里直接输入账号密码即可,不用再写访问步骤
cy.get('input[name=username]').type('jane.lane')
// ...
})
})
三、灵活控制用例:想跑哪个就跑哪个
测试多了之后,总不能每次都把所有用例跑一遍。Cypress提供了几个小技巧,让你能灵活选择要执行的用例:
-
只跑某个用例 :在
it()
后面加.only()
,比如it.only('只跑这个用例', ...)
,其他用例都会被跳过。 -
跳过某个用例 :在
it()
后面加.skip()
,比如it.skip('跳过这个用例', ...)
,这个用例不会执行。 -
按条件执行 :在代码里用
if
判断,比如根据环境变量决定是否执行某个用例:javascriptit('根据环境决定是否执行', function() { if (Cypress.env('runFlag') === 1) { // 执行测试步骤 } else { this.skip() // 跳过用例 } })
四、动态生成用例:一条代码跑多种场景
如果多个测试场景的步骤完全一样,只是输入数据不同(比如测试登录时,分别用正确密码、空密码、错误密码),没必要写多个重复的用例。可以用"数据驱动"的思路,根据数据动态生成用例:
-
先准备测试数据(比如一个数组):
javascriptconst testData = [ { summary: '正确密码登录', username: 'jane', password: '123', expectSuccess: true }, { summary: '空密码登录', username: 'jane', password: '', expectSuccess: false }, { summary: '错误密码登录', username: 'jane', password: '456', expectSuccess: false } ]
-
循环数据生成用例:
javascriptdescribe('登录功能', function() { testData.forEach(data => { it(data.summary, function() { cy.get('input[name=username]').type(data.username) cy.get('input[name=password]').type(data.password) cy.get('form').submit() // 根据预期结果断言 if (data.expectSuccess) { cy.url().should('include', '/dashboard') } else { cy.get('.error').should('be.visible') } }) }) })
这样一来,加新场景只需在数据里加一条,不用改测试代码,特别方便。
五、断言:判断测试结果对不对
断言就是"判断测试结果是否符合预期",比如"登录成功后URL应该包含/dashboard""错误提示应该显示"。Cypress支持多种断言方式,最常用的是:
- should() :直接跟在命令后面,比如
cy.url().should('include', '/dashboard')
(判断URL包含指定路径)。 - expect() :单独写断言,比如
expect(1 + 1).to.equal(2)
(判断计算结果正确)。
常用断言场景:
javascript
// 元素是否可见
cy.get('.error').should('be.visible')
// 文本是否包含指定内容
cy.get('h1').should('contain', '欢迎回来')
// 输入框的值是否正确
cy.get('input[name=username]').should('have.value', 'jane')
// 数组长度是否符合预期
cy.get('li').should('have.length', 3)
六、测试运行器:实时看测试过程
Cypress的测试运行器(Test Runner)特别好用,能实时展示测试步骤和页面状态:
- 命令日志:左边显示每个步骤的执行情况,绿色对勾表示成功,红色叉号表示失败。
- 时间穿梭:鼠标悬停在步骤上,右边会显示当时的页面状态,方便回溯哪里出了问题。
- 元素定位辅助:点击界面上的"定位器"按钮,选择页面元素,Cypress会自动推荐定位方式,避免定位失败。