第2章:数据驱动测试
本章演示了如何通过不同的测试数据重复执行测试。
到目前为止,我们将要测试的数据硬编码到测试函数中。如果我们添加更多测试数据,函数可能看起来像这样
QCOMPARE(QString("hello").toUpper(), QString("HELLO")); QCOMPARE(QString("Hello").toUpper(), QString("HELLO")); QCOMPARE(QString("HellO").toUpper(), QString("HELLO")); QCOMPARE(QString("HELLO").toUpper(), QString("HELLO"));
为了防止函数因代码重复而变得杂乱,Qt Test 支持将测试数据添加到测试函数中。我们只需要向我们的测试类添加另一个私有槽。
class TestQString: public QObject { Q_OBJECT private slots: void toUpper_data(); void toUpper(); };
编写数据函数
测试函数关联的数据函数在其名称末尾附加 _data
。我们的数据函数看起来像这样
void TestQString::toUpper_data() { QTest::addColumn<QString>("string"); QTest::addColumn<QString>("result"); QTest::newRow("all-lower") << "hello" << "HELLO"; QTest::newRow("mixed") << "Hello" << "HELLO"; QTest::newRow("all-upper") << "HELLO" << "HELLO"; }
首先,我们使用 QTest::addColumn() 函数定义测试表的两个元素:一个测试字符串以及将该字符串应用 QString::toUpper() 函数后的预期结果。
然后,我们使用 QTest::newRow() 函数向表格中添加一些数据。如果需要格式化行名称,例如在迭代生成多行数据时,我们还可以使用 QTest::addRow()。每行数据将成为测试表中的单独一行。
QTest::newRow() 传递一个参数:一个将与数据集相关联的名称,并在测试日志中用于标识数据行。QTest::addRow() 传递一个(printf
強制风格)格式化字符串,后跟用于替换格式化字符串中格式化标记的参数。然后,我们将数据集流式传输到新的表格行中。首先是一个任意的字符串,然后是该字符串应用 QString::toUpper() 函数后的预期结果。
您可以将测试数据视为一个二维表格。在我们的例子中,它有两个名为 string
和 result
的列和三行。此外,每行都与一个名称和索引相关联
索引 | 名称 | 字符串 | 结果 |
---|---|---|---|
0 | 全部小写 | "hello" | HELLO |
1 | 混合 | "Hello" | HELLO |
2 | 全部大写 | "HELLO" | HELLO |
数据流式传输到行中时,每个数据都会被断言为与提供其值的列的数据类型相匹配。如果任何断言失败,则测试被中止。
在给定测试函数的数据表中,行和列的名称应该是唯一的:如果两行共享一个名称,或者两列共享一个名称,那么(自 Qt 6.5 起)将生成一个警告。有关如何将警告视为错误的信息,请参阅 qWarning(),有关如何清除其他警告的信息,请参阅 Test for Warnings
重写测试函数
现在我们可以重写测试函数
void TestQString::toUpper() { QFETCH(QString, string); QFETCH(QString, result); QCOMPARE(string.toUpper(), result); }
TestQString::toUpper() 函数将被执行三次,一次对应于我们在关联的 TestQString::toUpper_data() 函数中创建的测试表中的每个条目。
首先,我们使用 QFETCH() 宏获取数据集的两个元素。QFETCH() 函数接受两个参数:元素的类型和元素名称。然后,我们使用 QCOMPARE() 宏执行测试。
这种方法使我们能够很容易地在不修改测试本身的情况下向测试中添加新数据。
准备独立的可执行文件
同样地,要使我们的测试用例成为一个独立可执行文件,需要以下两行代码
QTEST_MAIN(TestQString)
#include "testqstring.moc"
和之前一样,QTEST_MAIN() 宏扩展为一个简单的主方法 main(),它将运行所有的测试函数;由于我们的测试类声明和实现都在一个 .cpp 文件中,我们还需要包含生成的 moc 文件,以便使 Qt 的反射工作。
构建可执行文件
您可以使用 CMake 或 qmake 构建测试用例的可执行文件。
使用 CMake 构建
在您的 CMakeLists.txt 文件中配置您的构建设置
# Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause cmake_minimum_required(VERSION 3.16) project(tutorial2 LANGUAGES CXX) find_package(Qt6 REQUIRED COMPONENTS Core Gui Test Widgets) qt_standard_project_setup() qt_add_executable(tutorial2 testqstring.cpp ) set_target_properties(tutorial2 PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) target_link_libraries(tutorial2 PRIVATE Qt6::Core Qt6::Gui Qt6::Test Qt6::Widgets ) install(TARGETS tutorial2 BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) qt_generate_deploy_app_script( TARGET tutorial2 OUTPUT_SCRIPT deploy_script NO_UNSUPPORTED_PLATFORM_ERROR ) install(SCRIPT ${deploy_script})
接下来,从命令行运行 cmake
或使用位于 Qt-prefix/<version>/<platform>/bin/qt-cmake
的 qt-cmake
方便脚本
<Qt-prefix>/<version>/<platform>/bin/qt-cmake <source-dir> <build-dir> -G Ninja
然后,运行您首选的生成工具来构建可执行文件。在这个例子中,我们使用 Ninja。
ninja
使用 qmake 构建
在您的 .pro
文件中配置您的构建设置
QT += widgets testlib SOURCES = testqstring.cpp # install target.path = $$[QT_INSTALL_EXAMPLES]/qtestlib/tutorial2 INSTALLS += target
接下来,运行 qmake
,最后运行 make
来构建您的可执行文件
qmake make
运行可执行文件
运行生成的可执行文件应给出以下输出
********* Start testing of TestQString ********* Config: Using QtTest library %VERSION%, Qt %VERSION% PASS : TestQString::initTestCase() PASS : TestQString::toUpper(all-lower) PASS : TestQString::toUpper(mixed) PASS : TestQString::toUpper(all-upper) PASS : TestQString::cleanupTestCase() Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms ********* Finished testing of TestQString *********
© 2024 Qt 公司 Ltd. 本文档中的文档贡献者是各自的版权所有者。本提供在此的文档是在自由软件基金会(Free Software Foundation)发布的 GNU 自由文档许可协议版本 1.3 条件下许可的。Qt 及相关商标是芬兰以及/或其他国家的 Qt 公司有限公司的商标。所有其他商标均为其各自所有者的财产。