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

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

录制生成Web脚本

1. 项目创建

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

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

2. 开始录制脚本

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

打开【录制设置...】

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

录制设置界面

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

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

首页

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

填写信息

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

订单界面

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

完成录制

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

自动生成脚本

3. 运行录制好的脚本

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

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

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

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

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

1. 编写用例场景

打开目录中的的.feature文件,用自然语言编写与刚刚的测试操作对应的业务场景。这是使测试变得更加易读、更加便于管理的重要的一步:
编写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文件中,并做对应的修改。

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

JavaScript
// 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变量定义在外部是因为接下来的很多步骤中都会使用这个变量,而每个步骤中的变量又是独立的(像函数一样)。

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

JavaScript
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"]', ticketNum);

    // Fill input[name="creditcard"]
    await page.fill('input[name="creditcard"]', creditCard);

    // Fill input[name="duetime"]
    await page.fill('input[name="duetime"]', dueDate);

    // Fill input[name="code"]
    await page.fill('input[name="code"]', code);

    // Click button[type="submit"]
    await page.click('button[type="submit"]');
});

对结果进行断言:

JavaScript
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脚本文件内容如下:

JavaScript
const { Util } = require('leanpro.common');
const { BeforeAll, AfterAll, Given, When, Then } = require('cucumber');
const assert = require('assert');
const { chromium } = require('leanpro.web');

let browser, context;

BeforeAll(async function () {
    browser = await chromium.launch({
        headless: false
    });
    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"]', ticketNum);

    // Fill input[name="creditcard"]
    await page.fill('input[name="creditcard"]', creditCard);

    // Fill input[name="duetime"]
    await page.fill('input[name="duetime"]', dueDate);

    // 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"]'));
});

执行

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

results matching ""

    No results matching ""