Squish for Web: 基于模型的测试

教程:基于模型的测试

本教程向您展示如何利用模型来测试您的应用程序。这种方法称为基于模型的测试(MBT)。您将学习如何使用 Squish 创建、运行和修改 MBT 模型和测试。您将使用 Addressbook 应用程序。在本教程结束时,您将能够为测试自己的应用程序创建模型。

基于模型的测试简介

基于模型的测试是一种使用模型进行测试的测试方法。基本思想是设计 MBT 模型来描述被测应用程序(AUT),然后使用这些模型作为测试设计规范。

模型应提供正式的详细信息,足以通过遍历模型来手动和自动创建测试用例。

这种测试方式,类似于 BDD,旨在与 AUT 的开发和生命周期紧密集成。它可以拉近利益相关者的距离,统一沟通语言,并简化测试自动化的过程。

Squish 概念

  • 模型 - 测试基础的抽象表示。它可以用来建模不同的方面,如测试本身、工作流程、AUT 的行为或测试数据。
  • 步骤 - 抽象地描述应在测试期间发生的活动。例如,启动 AUT、向通讯录添加新联系人或编辑地址簿中的现有地址。步骤通过包含描述性名称的圆形矩形进行视觉表示。
  • 连接 - 源步骤和目标步骤之间的有向关系。它以两步骤之间的箭头进行视觉表示,指示方向。
  • Squish 步骤图 - 代表 MBT 模型或其部分的可视化图。该图旨在集中在应用程序的工作流程上而非数据。它由步骤及其之间的连接组成。每个连接都显示了步骤可以执行的可能的顺序。Squish MBT 功能的初始版本中,每个模型只支持一个图。
  • 路径 - 路径是通过给定模型的实际方式。它描述了在基于模型的测试中应采取的确切连续步骤。模型不应包含无效的路径 - 如果 AUT 正确工作,执行路径中的连续步骤不应导致失败。

实现

以下说明将指导您通过设计全面的 MBT 模型和基于它创建测试用例的迭代过程。

获取示例测试套件

SQUISHDIR/examples/web/addressbook 文件夹包含示例测试套件(例如 suite_mbt_01_*suite_mbt_02_*),展示本教程的不同阶段。我们鼓励您在需要交叉检查您的解决方案时检查它们。

选择 文件 > 打开测试套件... 定位测试套件。点击 下一步完成 按钮。打开它。

创建测试套件

首先,我们需要创建一个测试套件,这是所有测试用例的容器。启动 squishide 并选择 文件 > 新建测试套件。请按照 新建测试套件 向导,提供测试套件名称,选择您选择的 Web Toolkit 和脚本语言。有关创建新测试套件的更多信息,请参阅创建测试套件

启动本地 Web 服务器

要使用示例通讯录应用程序,需要启动本地网络服务器。为此,请按照使用示例部分Squish for Web教程的指示操作。

创建MBT模型

测试套件准备就绪后,就可以创建一个模型文件。要这么做,请选择文件 > 新建 > MBT模型文件。这将打开新建MBT模型对话框。

在对话框中,提供MBT模型文件名 "管理联系人",并选择您的测试套件。勾选在测试套件中创建共享文件,以便模型可以被多个测试案例使用。

点击完成按钮后,将打开一个新建Squish步骤图的MBT模型编辑器。

在此阶段,您可以开始创建第一个MBT模型。您看到的图形是一个Squish步骤图,其中有一个黑色圆点,代表初始步骤。

注意:初始步骤 - 一个专用的步骤,用作Squish步骤图的入口点。它以填充的黑色圆圈形式在视觉上表示,没有对应的步骤实现。

迭代1

在这个迭代中,我们将创建一个简单的模型,允许我们测试将单个条目添加到通讯录的工作流。

添加步骤

要添加新步骤,请确保编辑模式:添加步骤处于活动状态,例如通过点击模型编辑器中的按钮。接下来,点击新步骤应添加的位置。输入步骤名称,然后通过按Enter键或点击矩形外退出以确认。

将以下步骤添加到图中

  • 创建新通讯录
  • 打开添加视图
  • 填写联系人信息
  • 确认
  • 验证新的条目是否已添加

注意:在Squish步骤图中,我们建议将步骤命名为以动词开头,即使是验证步骤。
使用检查按钮是否禁用而不是按钮应该禁用
这将有助于保持步骤风格的一致性。

添加所有条目后,您的图形可能看起来像这样

连接步骤

当所有步骤都在图中时,就需要将它们以展示在应用程序中可以执行的工作流程的方式连接起来。为此,通过点击图标激活编辑模式:连接步骤。现在,使用鼠标光标连接图形中的步骤。

在此阶段,您可能需要使用编辑模式:编辑步骤)来移动步骤,使模型更整洁、更易于理解。

创建测试案例

在添加和连接所有步骤后,是时候创建第一个MBT测试案例了。

您可以通过以下方式创建New MBT Test Case

一旦向导打开,请确保选择MBT测试案例,并选择一个模型文件。最后,单击完成按钮。

还为打开的模型创建新的测试案例也是可能的。要做到这一点,单击模型编辑器的新建MBT测试案例 )工具栏按钮。这会创建一个带有默认名称的新测试案例,您可以轻松更改。

创建新的测试案例后,MBT测试案例编辑器将打开。

编辑器显示用于其创建的模型。现在,请在图中选择步骤序列。路径从最初选择的初始步骤开始。与选定的每个步骤连接的步骤都显示一个绿色的加号按钮。

单击它可以突出显示步骤矩形,显示步骤编号,并将步骤添加到路径列表。按照先前教程步骤中添加的连接操作 - 从创建新地址簿开始,以验证新条目已添加结束。这样,您创建了代表测试案例工作流的路径。

步骤实现

现在是时候实现步骤背后的逻辑了。步骤脚本可以录制为代码段或由测试开发者编写。

通过录制代码段记录步骤

注意:要了解更多关于录制代码段的信息,请访问如何编辑和调试测试脚本

首先,为所有添加的步骤创建缺少的步骤实现。返回到模型编辑器,激活编辑模式:编辑步骤模式( ),并选择任何步骤。单击该字段旁边的( )按钮,并选择创建缺失的步骤实现选项。这将为Manage contacts.py文件打开一个脚本编辑器,包含五个新的步骤函数。此时,它们都调用test.warning()函数来报告缺失的步骤实现。

在每个带有test.warning()调用的行上设置断点。单击该行,从主菜单选择运行 > 切换断点。您最终会在脚本中有五个断点。

在测试执行过程中录制代码段时,Squish需要连接到AU。在代表第一个步骤的函数中警告之前使用地址簿应用程序的URL调用startBrowser(url)函数。

@mbt.step("Create new address book")
def step():
    startBrowser("http://localhost:9090/AddressBook.html")
    test.warning("TODO implement Create new address book")
mbt.step("Create new address book", function() {
    startBrowser("http://localhost:9090/AddressBook.html");
    test.warning("TODO implement Create new address book");
});
mbt::step("Create new address book", sub {
    startBrowser("http://localhost:9090/AddressBook.html");
    test::warning("TODO implement Create new address book");
});
Mbt::step("Create new address book") do
    startBrowser("http://localhost:9090/AddressBook.html")
    Test.warning "TODO implement Create new address book"
end
mbt step "Create new address book" {} {
    invoke startBrowser "http://localhost:9090/AddressBook.html"
    test warning "TODO implement Create new address book"
}

这将使AU在触发测试执行时启动。您可以通过以下方式做到这一点:

  • 单击路径列表下方的运行MBT测试案例 按钮
  • 单击测试案例列表中测试案例名称旁的运行测试 按钮文本
  • 从Squish IDE菜单中选择运行 > 运行测试案例

等待Squish到达create_new_addressbook步骤中的第一个断点。您将看到IDE的调试视图。开始录制一个代码片段,执行创建新地址簿所需的所有操作,例如,点击新建按钮,然后在AUT中使用确定按钮确认删除所有条目。之后,使用Squish的控制栏停止录制。一旦回到Squish IDE,通过点击主工具栏的继续按钮来恢复执行。

重复上述过程以处理您创建的所有断点。每次录制代码片段时,仅执行当前步骤描述的操作。

  • 打开添加视图 - 点击添加按钮
  • 填写联系信息 - 输入名、姓、电子邮件和电话
  • 确认 - 点击保存按钮
  • 验证新条目已添加 - 为地址簿表添加一个rowCount 属性验证点
使用提供的示例

示例测试套件suite_mbt_01_*已经包含您迄今为止创建的所有步骤的实现。如果您在某个地方迷失了方向,我们鼓励您查看此测试套件,并根据需要修复代码。

执行测试用例

通过选择运行 > 删除所有断点来移除所有添加的断点。删除所有test.warning(...)调用。当执行完成后,您可以在测试结果视图中检查执行结果。双击表示步骤的结果条目将焦点切换到模型中的相应步骤。要跳转到步骤实现,展开步骤消息并双击任一内部测试结果条目。

迭代2

在本迭代中,您将扩展图并将创建新的MBT测试用例。

添加步骤

将以下步骤添加到图中

  • 终止
  • 验证未添加新条目

添加所有条目后,您的图可能看起来与这个相似

连接步骤

激活编辑模式:连接步骤)并按照显示两种可能工作流程的方式连接新步骤

创建更多测试用例

这些新步骤和连接使我们能够创建两个额外的路径,即两个额外的测试用例。像以前一样,从现有模型中创建一个新的测试用例,并通过选择步骤来创建以下路径
创建新地址簿 > 打开添加对话框 > 终止 > 验证未添加新条目

之后,创建另一个测试用例,涵盖最后可能的路径
创建新地址簿 > 打开添加对话框 > 插入联系方式 > 终止 > 验证未添加新条目

步骤实现

就像第一次迭代期间一样,您可以在新函数中创建缺失的步骤实现并添加断点。然后,执行新创建的测试用例并记录缺失的代码片段。

终止步骤应点击取消按钮。验证未添加新条目应验证地址簿条目数量等于0。

您还可以使用下述代码片段

@mbt.step("abort")
def step():
    clickButton(waitForObject({"tagName":"SPAN", "simplifiedInnerText":"Cancel"}))

@mbt.step("vp_no_new_entry")
def step():
    test.compare(
        # rowCount == 1 as the value includes the table header
        waitForObjectExists({"id":"addresses", "tagName": "TABLE"}).rowCount,
        1,
        "Only the header should be in the address book"
    )
mbt.step("abort", function() {
    clickButton(waitForObject({"tagName":"SPAN", "simplifiedInnerText":"Cancel"}));
});

mbt.step("vp_no_new_entry", function() {
    // rowCount == 1 as the value includes the table header
    test.compare(waitForObjectExists({"id": "addresses", "tagName": "TABLE"}).rowCount,
        1, "Only the header should be in the address book");
});
mbt::step("abort", sub {
    clickButton(waitForObject({"tagName" => "SPAN", "simplifiedInnerText" => "Cancel"}));
});

mbt::step("vp_no_new_entry", sub {
    # rowCount == 1 as the value includes the table header
    test::compare(
        waitForObjectExists({"id" => "addresses", "tagName" => "TABLE"})->rowCount,
        1,
        "Only the header should be in the address book"
    )
});
Mbt::step("abort") do
    clickButton(waitForObject({:simplifiedInnerText => "Cancel", :tagName => "SPAN"}))
end

Mbt::step("vp_no_new_entry") do
    Test.compare(
        # rowCount == 1 as the value includes the table header
        waitForObjectExists({:id => "addresses", :tagName => "TABLE"}).rowCount,
        1, "Only the header should be in the address book"
    )
end
mbt step "abort" {} {
    invoke clickButton [waitForObject [::Squish::ObjectName simplifiedInnerText Cancel tagName SPAN]]
}

mbt step "vp_no_new_entry" {} {
    # rowCount == 1 as the value includes the table header
    test compare [property get [waitForObjectExists [::Squish::ObjectName id addresses tagName TABLE]] rowCount] 1 "Only the header should be in the address book"
}

在这种情况下,记得填写新步骤的实现:字段,使其与步骤定义的步骤实现标识符相匹配。

执行测试套件

这次,点击 运行测试套件() 按钮执行整个测试套件。三个 MBT 测试用例的执行结果将可用在测试结果视图中。

使用提供的示例

示例 suite_mbt_02_* 测试套件实现了本教程的所有步骤。您可以自由地使用它作为全面参考或比较您的实现。

常见问题

测试用例与模型不匹配

由于模型中进行的更改,一些之前创建的路径可能不再有效,例如,两个步骤之间的连接被删除。

这将以错误指示符显示在测试用例中,并在执行过程中导致错误。模型可能会随着时间的推移而发展,请记得相应地审查和更新您的测试用例和路径。

缺少步骤实现

如果步骤的 实现 没有引用有效的步骤实现,当测试执行通过该步骤时,Squish 将抛出缺少步骤实现错误。

©2024 Qt 公司有限公司。本文档的贡献版权属于各自的持有者。
本提供的文档遵循 GNU 自由文档许可证 1.3 版本 的条款,由自由软件基金会发布。
Qt 及相关标志是芬兰和/或世界其他国家的 Qt 公司的商标。所有其他商标均为各自所有者的财产。