演练:录制和回放Web自动化测试项目
在这一演练中,我们将使用CukeTest提供的Web录制功能来快速的完成Web自动化测试项目的编写。
录制生成Web脚本
1. 项目创建
首先打开CukeTest客户端,创建项目,注意项目模版选择的是Web模版,而不是Selenium Web。前者使用Web录制的方式生成脚本,而后者需要手写脚本。
项目创建完成之后,会自动打开项目首页。
2. 安装依赖
Web 自动化项目模板中含有外部依赖库,创建项目完成之后会有对应的提示,根据提示安装依赖库即可。
点击【打开命令行窗口】按钮,会弹出系统的命令行窗口。
在命令行窗口中输入 npm install
命令进行安装。
3. 开始录制脚本
可以在CukeTest中直接点击【录制】按钮进行录制,也可以在【录制选项】中对Web相关功能进行录制配置;
打开【录制设置…】
起始网站使用CukeTest提供的测试页面(需要联网): https://cuketest.github.io/apps/shopping/
点击【开始录制】 进行录制; 我们准备录制一个提交表单的场景:
- 在Mall网站首页点击【Pay parking】(支付停车费)链接到 Payment页面
- 在表单中输入对应的信用卡数据(当然不会验证格式,也不会真的提交),点击【Pay】进行提交。
- 系统会跳转到订单页面,在订单页面能够显示出提交的数据
录制完成后点击【停止录制】
接着返回CukeTest中可以看到已经生成好的自动化脚本。
4. 运行录制好的脚本
点击 工具栏【只显示脚本列】切换CukeTest视图为只显示脚本栏,点击【运行脚本】:
可以看到能够自动化运行将刚才录制的脚本。
整合自动化测试用例与代码
上面的操作仅仅只是将自动化操作部分录制下来了,也就是只能回放操作步骤,还不能算是测试,因为测试脚本中除了测试操作以外还需要有断言部分,即对测试操作的结果进行验证。
下面将录制的脚本与自动化测试结合起来。
1. 编写用例场景
打开目录中的的.feature
文件,用自然语言编写与刚刚的测试操作对应的业务场景。这是使测试变得更加易读、更加便于管理的重要的一步:
接下来可以切换剧本的编辑模式到【文本】模式,将以下内容复制进去,再切换回【可视】模式:
# language: zh-CN
功能: 表单提交功能验证
验证表单提交的字段显示功能
场景: 提交表单到Payment页面
假如打开网站首页"https://cuketest.github.io/apps/shopping/"
当点击Pay parking到表单提交页面
当输入表单数据,点击Paying按钮
| TICKET | CREDIT CARD | DUE DATE | CODE |
| 187465 | 55431234423137865 | 11/25 | 908 |
那么在Payment 页面中能够显示出上述表单中输入的值
第三步中的表格是通过右击步骤选择【添加表】来添加的,关于步骤中的数据表,是用于向步骤传递较为复杂的键值类型的数据,具体可以点击查看数据表。
2. 生成代码样例
打开definitions目录下的definitions.js
文件,点击剧本中每个步骤后面的灰色按钮,可以definitions.js
文件中生成对应的代码样例。
将录制的代码按照操作步骤的顺序,分别复制到definitions.js
文件中,并做对应的修改。
打开网站首页代码修改之后如下
// page 变量在其它操作步骤中也使用,定义为外部变量
let page;
Given("打开网站首页{string}", async function (url) {
// Open new page
page = await context.newPage();
// Go to https://cuketest.github.io/apps/shopping/
await page.goto(url);
});
将
page
变量定义在外部是因为接下来的很多步骤中都会使用这个变量,而每个步骤中的变量又是独立的(像函数一样)。
输入表单的的数据需要在下一个操作步骤中作为验证数据,将这些数据对应的变量设置为外部变量;
let ticketNum,creditCard,dueDate,code;
When("输入表单数据,点击Paying按钮", async function (table) {
// 获取table中的值
const tableData = table.hashes()[0];
ticketNum = tabledata['TICKET'];
creditCard = tabledata['CREDIT CARD'];
dueDate = tabledata['DUE DATE'];
code = tabledata['CODE'];
// Fill input[name="ticketnum"]
await page.fill('input[name="ticketnum"]', ticket_num);
// Fill input[name="creditcard"]
await page.fill('input[name="creditcard"]', credit_card);
// Fill input[name="duetime"]
await page.fill('input[name="duetime"]', due_date);
// Fill input[name="code"]
await page.fill('input[name="code"]', code);
// Click button[type="submit"]
await page.click('button[type="submit"]');
});
对结果进行断言:
Then("在Payment 页面中能够显示出上述表单中输入的值", async function () {
assert.equal(ticketNum, await page.innerText('[data-label="Ticket Number"]'));
assert.equal(creditCard, await page.innerText('[data-label="Credit card"]'));
assert.equal(dueDate, await page.innerText('[data-label="Due Date"]'));
assert.equal(code, await page.innerText('[data-label="Code"]'));
});
整合后的完整脚本
结合剧本整合了录制脚本后,整个definitions.js
脚本文件内容如下:
const { Util } = require('leanpro.common');
const { BeforeAll, AfterAll, Given, When, Then } = require('cucumber');
const assert = require('assert');
const { chromium } = require('leanpro.web');
const chromePaths = require('chrome-paths');
let browser, context;
BeforeAll(async function () {
browser = await chromium.launch({
headless: false,
executablePath: chromePaths.chrome
});
context = await browser.newContext();
});
AfterAll(async function () {
// 清理会话,关闭浏览器
// ---------------------
await context.close();
await browser.close();
});
// page 变量在其它操作步骤中也使用,定义为外部变量
let page;
Given("打开网站首页{string}", async function (url) {
// Open new page
page = await context.newPage();
// Go to https://cuketest.github.io/apps/shopping/
await page.goto(url);
});
When("点击Pay parking到表单提交页面", async function () {
// Click text=/.*Pay parking.*/
await page.click('text=/.*Pay parking.*/');
// assert.equal(page.url(), 'https://cuketest.github.io/apps/shopping/pagar-estacionamento.html');
});
let ticketNum,creditCard,dueDate,code;
When("输入表单数据,点击Paying按钮", async function (table) {
// 获取table中的值
const tableData = table.hashes()[0];
ticketNum = tabledata['TICKET'];
creditCard = tabledata['CREDIT CARD'];
dueDate = tabledata['DUE DATE'];
code = tabledata['CODE'];
// Fill input[name="ticketnum"]
await page.fill('input[name="ticketnum"]', ticket_num);
// Fill input[name="creditcard"]
await page.fill('input[name="creditcard"]', credit_card);
// Fill input[name="duetime"]
await page.fill('input[name="duetime"]', due_date);
// Fill input[name="code"]
await page.fill('input[name="code"]', code);
// Click button[type="submit"]
await page.click('button[type="submit"]');
});
Then("在Payment 页面中能够显示出上述表单中输入的值", async function () {
assert.equal(ticketNum, await page.innerText('[data-label="Ticket Number"]'));
assert.equal(creditCard, await page.innerText('[data-label="Credit card"]'));
assert.equal(dueDate, await page.innerText('[data-label="Due Date"]'));
assert.equal(code, await page.innerText('[data-label="Code"]'));
});
执行
点击【运行项目】,可以看到自动化执行完成后生成对应的测试报告。