演练:录制和回放Web自动化测试项目

在这一演练中,我们将使用CukeTest提供的Web录制功能来快速的完成Web自动化测试项目的编写。

录制生成Web脚本

1. 项目创建

首先打开CukeTest客户端,创建项目,注意项目模版选择的是Web模版,而不是Selenium Web。前者使用Web录制的方式生成脚本,而后者需要手写脚本。 创建项目

项目创建完成之后,会自动打开项目首页。

2. 安装依赖

Web 自动化项目模板中含有外部依赖库,创建项目完成之后会有对应的提示,根据提示安装依赖库即可。

项目提示——安装依赖

点击【打开命令行窗口】按钮,会弹出系统的命令行窗口。

打开命令行窗口

在命令行窗口中输入 npm install 命令进行安装。 image.png

3. 开始录制脚本

可以在CukeTest中直接点击【录制】按钮进行录制,也可以在【录制选项】中对Web相关功能进行录制配置; image.png

打开【录制设置…】

起始网站使用CukeTest提供的测试页面(需要联网): https://cuketest.github.io/apps/shopping/

录制设置界面

点击【开始录制】 进行录制; 我们准备录制一个提交表单的场景:

  1. 在Mall网站首页点击【Pay parking】(支付停车费)链接到 Payment页面

首页

  • 在表单中输入对应的信用卡数据(当然不会验证格式,也不会真的提交),点击【Pay】进行提交。

填写信息

  • 系统会跳转到订单页面,在订单页面能够显示出提交的数据

订单界面

录制完成后点击【停止录制】 完成录制

接着返回CukeTest中可以看到已经生成好的自动化脚本。 自动生成脚本

4. 运行录制好的脚本

点击 工具栏【只显示脚本列】切换CukeTest视图为只显示脚本栏,点击【运行脚本】:
切换视图

运行脚本 可以看到能够自动化运行将刚才录制的脚本。

整合自动化测试用例与代码

上面的操作仅仅只是将自动化操作部分录制下来了,也就是只能回放操作步骤,还不能算是测试,因为测试脚本中除了测试操作以外还需要有断言部分,即对测试操作的结果进行验证。

下面将录制的脚本与自动化测试结合起来。

1. 编写用例场景

打开目录中的的.feature文件,用自然语言编写与刚刚的测试操作对应的业务场景。这是使测试变得更加易读、更加便于管理的重要的一步:
编写Feature文件

接下来可以切换剧本的编辑模式到【文本】模式,将以下内容复制进去,再切换回【可视】模式:

  1. # language: zh-CN
  2. 功能: 表单提交功能验证
  3. 验证表单提交的字段显示功能
  4. 场景: 提交表单到Payment页面
  5. 假如打开网站首页"https://cuketest.github.io/apps/shopping/"
  6. 当点击Pay parking到表单提交页面
  7. 当输入表单数据,点击Paying按钮
  8. | TICKET | CREDIT CARD | DUE DATE | CODE |
  9. | 187465 | 55431234423137865 | 11/25 | 908 |
  10. 那么在Payment 页面中能够显示出上述表单中输入的值

第三步中的表格是通过右击步骤选择【添加表】来添加的,关于步骤中的数据表,是用于向步骤传递较为复杂的键值类型的数据,具体可以点击查看数据表

2. 生成代码样例

打开definitions目录下的definitions.js文件,点击剧本中每个步骤后面的灰色按钮,可以definitions.js文件中生成对应的代码样例。

生成步骤定义

将录制的代码按照操作步骤的顺序,分别复制到definitions.js文件中,并做对应的修改。

打开网站首页代码修改之后如下

  1. // page 变量在其它操作步骤中也使用,定义为外部变量
  2. let page;
  3. Given("打开网站首页{string}", async function (url) {
  4. // Open new page
  5. page = await context.newPage();
  6. // Go to https://cuketest.github.io/apps/shopping/
  7. await page.goto(url);
  8. });

page变量定义在外部是因为接下来的很多步骤中都会使用这个变量,而每个步骤中的变量又是独立的(像函数一样)。

输入表单的的数据需要在下一个操作步骤中作为验证数据,将这些数据对应的变量设置为外部变量;

  1. let ticketNum,creditCard,dueDate,code;
  2. When("输入表单数据,点击Paying按钮", async function (table) {
  3. // 获取table中的值
  4. const tableData = table.hashes()[0];
  5. ticketNum = tabledata['TICKET'];
  6. creditCard = tabledata['CREDIT CARD'];
  7. dueDate = tabledata['DUE DATE'];
  8. code = tabledata['CODE'];
  9. // Fill input[name="ticketnum"]
  10. await page.fill('input[name="ticketnum"]', ticket_num);
  11. // Fill input[name="creditcard"]
  12. await page.fill('input[name="creditcard"]', credit_card);
  13. // Fill input[name="duetime"]
  14. await page.fill('input[name="duetime"]', due_date);
  15. // Fill input[name="code"]
  16. await page.fill('input[name="code"]', code);
  17. // Click button[type="submit"]
  18. await page.click('button[type="submit"]');
  19. });

对结果进行断言:

  1. Then("在Payment 页面中能够显示出上述表单中输入的值", async function () {
  2. assert.equal(ticketNum, await page.innerText('[data-label="Ticket Number"]'));
  3. assert.equal(creditCard, await page.innerText('[data-label="Credit card"]'));
  4. assert.equal(dueDate, await page.innerText('[data-label="Due Date"]'));
  5. assert.equal(code, await page.innerText('[data-label="Code"]'));
  6. });

整合后的完整脚本

结合剧本整合了录制脚本后,整个definitions.js脚本文件内容如下:

  1. const { Util } = require('leanpro.common');
  2. const { BeforeAll, AfterAll, Given, When, Then } = require('cucumber');
  3. const assert = require('assert');
  4. const { chromium } = require('leanpro.web');
  5. const chromePaths = require('chrome-paths');
  6. let browser, context;
  7. BeforeAll(async function () {
  8. browser = await chromium.launch({
  9. headless: false,
  10. executablePath: chromePaths.chrome
  11. });
  12. context = await browser.newContext();
  13. });
  14. AfterAll(async function () {
  15. // 清理会话,关闭浏览器
  16. // ---------------------
  17. await context.close();
  18. await browser.close();
  19. });
  20. // page 变量在其它操作步骤中也使用,定义为外部变量
  21. let page;
  22. Given("打开网站首页{string}", async function (url) {
  23. // Open new page
  24. page = await context.newPage();
  25. // Go to https://cuketest.github.io/apps/shopping/
  26. await page.goto(url);
  27. });
  28. When("点击Pay parking到表单提交页面", async function () {
  29. // Click text=/.*Pay parking.*/
  30. await page.click('text=/.*Pay parking.*/');
  31. // assert.equal(page.url(), 'https://cuketest.github.io/apps/shopping/pagar-estacionamento.html');
  32. });
  33. let ticketNum,creditCard,dueDate,code;
  34. When("输入表单数据,点击Paying按钮", async function (table) {
  35. // 获取table中的值
  36. const tableData = table.hashes()[0];
  37. ticketNum = tabledata['TICKET'];
  38. creditCard = tabledata['CREDIT CARD'];
  39. dueDate = tabledata['DUE DATE'];
  40. code = tabledata['CODE'];
  41. // Fill input[name="ticketnum"]
  42. await page.fill('input[name="ticketnum"]', ticket_num);
  43. // Fill input[name="creditcard"]
  44. await page.fill('input[name="creditcard"]', credit_card);
  45. // Fill input[name="duetime"]
  46. await page.fill('input[name="duetime"]', due_date);
  47. // Fill input[name="code"]
  48. await page.fill('input[name="code"]', code);
  49. // Click button[type="submit"]
  50. await page.click('button[type="submit"]');
  51. });
  52. Then("在Payment 页面中能够显示出上述表单中输入的值", async function () {
  53. assert.equal(ticketNum, await page.innerText('[data-label="Ticket Number"]'));
  54. assert.equal(creditCard, await page.innerText('[data-label="Credit card"]'));
  55. assert.equal(dueDate, await page.innerText('[data-label="Due Date"]'));
  56. assert.equal(code, await page.innerText('[data-label="Code"]'));
  57. });

执行

点击【运行项目】,可以看到自动化执行完成后生成对应的测试报告。 image.png