演练:创建Qt自动化测试项目
Qt桌面应用的测试常常都是由测试工程师们按照用例来手工测试,但对于大型应用来说,手工测试的耗时太长,可靠性跟覆盖率都存在不足。随着持续集成/交付/部署(CI/CD)的概念开始普及,Qt的测试也开始慢慢向自动化测试转变。为降低开发自动化测试的成本,我们提供了录制Qt应用生成自动化的能力。
在这一演练中,我们将使用CukeTest提供的Qt录制功能来快速的完成Qt自动化测试项目的编写。
录制生成Qt脚本
1. 项目创建
打开CukeTest客户端,创建项目,并填写项目名称,注意项目模版选择的是【Python】语言下的 【Qt】 模版。项目创建完成之后,会自动打开项目首页。
2. 开始录制脚本
在主界面点击Qt录制设置,将被测应用的路径填进去(也可以不写路径,开始录制后手动启动即可),就可以开始录制。
这里我们使用CukeTest自带的样例应用standarddialogs.exe
,录制一个操作文本对话框的场景:
- 打开文本对话框
- 修改文本框的内容
录制时的界面如下:
添加检查点
在自动化测试中,检查点(Checkpoint)是验证应用状态是否符合预期的关键部分。在CukeTest中,您可以在录制过程中快捷添加检查点。具体操作步骤如下:
快速打开检查点对话框:在录制时,通过按住Alt键并右击目标控件,您可以快速打开检查点对话框。这个功能让你能够在进行操作的同时,即时地添加验证步骤,提高测试脚本的编写效率。
添加属性检查点:对于本测试用例,我们将添加一个属性检查点来验证
QInputDialog::getText()
按钮旁的Label控件中的文本。在“属性检查点”列表中,选择“text”属性(其值应为“这是一些测试文本”),这就是我们要验证的目标属性。确认和插入检查点脚本:选择需要验证的属性后,点击
确认
按钮。相应的检查点脚本就会被插入到我们的录制脚本中。
如果需要添加图像检查点,只需切换到图像检查点标签页,并勾选需要检查的图片。这种检查点用于验证应用界面上特定图像的出现,非常适合那些以视觉元素为核心的测试场景。
接着可以继续操作被测应用,因为录制已经开始了的缘故,所有操作都会同步的生成自动化脚本,可以在编辑器中看到。当所有操作完成后,点击工具栏中的 “停止” 按钮,就录好了一个自动化脚本。录制生成的脚本内容如下:
import os
from leanproAuto import RunSettings, QtAuto
RunSettings.set({"slowMo": 1000, "reportSteps": True})
modelQt = QtAuto.loadModel(os.path.dirname(os.path.realpath(__file__)) + "/recording.tmodel")
#启动Qt应用"standarddialogs"
QtAuto.launchQtProcessAsync("C:/Program Files/LeanPro/CukeTest/bin/standarddialogs.exe")
modelQt.getApplication("standarddialogs").exists(10)
#点击 "QInputDialog::getMultiLineText"
modelQt.getButton("QInputDialog::getMultiLineText").click()
#设置控件值为"这是一些测试文本"
modelQt.getEdit("Edit").set("这是一些测试文本")
#点击 "OK"
modelQt.getButton("OK").click()
#检查属性
modelQt.getLabel("这是一些测试文本").checkProperty("text", "这是一些测试文本")
#关闭Qt应用"standarddialogs"
modelQt.getApplication("standarddialogs").quit()
3. 运行录制好的脚本
点击 工具栏【只显示脚本列】切换CukeTest视图为只显示脚本栏,点击【运行脚本】:
可以看到回放顺利的完成了,但是回放的操作速度并不是飞快,这是因为CukeTest的录制默认打开了“慢动作”这个开关,所以在生成的脚本中加入了slowMo
这个选项并设为1000,将各个操作的间隔延长到1秒,这里我们将其设为0就可以让自动化以最快的速度运行了。
生成的脚本中设置了
slowMo
的值:RunSettings = auto.runSettings // …… RunSettings.set({"slowMo": 1000, "reportSteps": True})
整合自动化测试用例与代码
上面的操作仅仅只是将自动化操作部分录制下来了,也就是只能回放操作步骤,还不能算是测试,因为测试脚本中除了测试操作以外还需要有断言部分,即对测试操作的结果进行验证。
下面将录制的脚本与自动化测试结合起来。
1. 创建应用模型
录制生成的代码运行需要依赖录制时使用的模型文件,所以在整合代码之前需要先创建本次测试需要的模型文件。这里可以直接使用录制生成的模型,将它拷贝到models
目录下,并重命名为model1.tmodel
。
如果项目中已经存在模型文件,您可以打开这个已有模型文件和新录制的模型文件。然后,通过将新录制的模型的根节点拖拽到已有的模型树中,实现模型的复制。接下来,右击复制生成的节点,选择“合并到兄弟节点”,完成模型的合并。这样,就可以在已有模型中使用新录制时操作到的控件对象。
此外,您也可以在录制的时候选择“录制到已有模型”,这会直接将新的控件对象保存到现有模型中,进一步简化整合过程。
2. 编写用例场景
打开目录中的.feature
文件,用自然语言编写与刚刚的测试对应的业务场景。这是使测试变得更加易读、更加便于管理的重要的一步:
接下来可以切换剧本的编辑模式到 文本 模式,将以下内容复制进去,再切换回 可视 模式:
步骤2中的文本是通过右击步骤选择【添加文本字符串】来添加的,详见步骤编辑。
Feature: 跨平台Qt应用自动化——输入对话框
输入对话框是由Qt的QInputDialog控件类实现的,在各种操作系统或CPU架构上都呈现同样的结构。
因此可以很轻松的实现跨平台自动化。
Scenario: 操作文本对话框
Given 打开文本对话框
When 修改文本框的内容为如下
"""
这是一些测试文本
"""
3. 修改conftest.py
conftest.py
是一个专门存放fixture的配置文件,pytest会自动识别和加载它。在CukeTest中,我们将被测应用的启动、关闭,测试环境的初始化等操作放在这个文件中。
打开根目录下的conftest.py
,修改其中的应用启动路径app_path
和模型文件路径。修改完成后,conftest.py
内容如下:
# conftest.py
from leanproAuto import QtAuto, Util
app_path = "C:/Program Files/LeanPro/CukeTest/bin/standarddialogs.exe"
model = QtAuto.loadModel("./models/model1.tmodel")
context = {}
# 等效于 BeforeAll Hook,在第一个测试开始前被调用
def pytest_sessionstart(session):
context["pid"] = QtAuto.launchQtProcessAsync(app_path)
# 等效于 AfterAll Hook,在所有测试结束后被调用
def pytest_sessionfinish(session):
Util.stopProcess(context["pid"])
这段代码主要完成以下几个任务:
- 应用路径:定义了被测试Qt应用的路径。
- 模型加载:加载了之前提到的模型文件,这对于界面自动化测试非常重要。
- 测试会话开始和结束:定义了在所有测试开始之前和结束之后执行的操作。这包括启动和关闭被测应用,确保测试环境的正确初始化和清理。
通过以上配置,我们的测试环境将为执行自动化测试脚本做好充分准备。
4. 编写步骤代码
现在,打开位于step_defs
目录下的test_feature1.py
文件来开始编写步骤定义代码。
pytest-bdd通过使用装饰器,将特定的Python函数与Gherkin语法编写的.feature文件中的步骤文本关联起来。例如:
from pytest_bdd import scenarios, given, when, then, parsers
# 使用parsers.parse来使步骤文本参数化,这里将接收一个"docString"参数
@when(parsers.parse("修改文本框的内容为如下\n{docString}"))
def edit_text_input(docString):
# 输入文本的逻辑处理
...
# 对于没有参数的步骤文本,可以直接使用字符串
@given("打开文本对话框")
def open_text_input():
# 打开文本对话框的逻辑处理
...
这里,parsers.parse
允许我们将步骤文本中的变量例如 {docString}
传递到步骤函数中作为参数。
接着,按照Feature文件中定义的步骤顺序,将录制得到的代码片段逐一复制到test_feature1.py
文件的相应步骤定义中,并根据实际测试需求进行调整和优化。
完成这一步骤后,您的test_feature1.py
文件将包含所有的步骤函数,它们将直接映射到Feature文件中定义的各个步骤。
为了进一步增强测试脚本,您可以使用Python的
assert
关键字添加验证点,以确认测试的预期结果。这是Python的内置断言机制,用于确认某个条件为真。您也可以利用checkProperty()方法更简便地验证GUI元素的属性。详细的检查点使用方法,请参考理解和使用检查点。
以下是更新后的test_feature1.py
示例,展示了完整的步骤定义及其实现:
# test_feature1.py
from pytest_bdd import scenarios, given, when, parsers
from leanproAuto import QtAuto
scenarios("../features")
model = QtAuto.loadModel('model1.tmodel')
@given("打开文本对话框")
def open_text_input():
model.getButton("QInputDialog::getMultiLineText").click()
@when(parsers.parse("修改文本框的内容为如下\n{docString}"))
def edit_text_input(docString):
print('content:', docString)
model.getEdit("Edit").set("这是一些测试文本")
model.getButton("OK").click()
labelControl = model.getButton("QInputDialog::getMultiLineText").next("Label")
textValue = labelControl.text()
#检查属性
labelControl.checkProperty("text", docString)
assert textValue == docString, "没有成功修改文本框内容"
执行
点击【运行项目】,可以看到自动化执行完成后生成对应的测试报告。
更多Qt自动化能力,参见跨平台Qt自动化