Chapter 2: Data Driven Testing
这一章, 我们讨论如何使用不同的测试数据运行多次同一个测试函数.
如下所示, 我们将在测试程序中添加多个测试数据:
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::newRow()需要一个参数: 数据关联的名称, 在测试日志中标识数据. 然后, 我们将数据集流式地传输到表行中. 先是一个任意字符串, 然后是对这个字符串经QString::toUpper()运算后的预期结果.
你可以将测试数据视作一个二维表格. 在示例中, 它有两列(string
和result
)和三行. 在每一行增加一个类似索引的名称:
index | name | string | result |
---|---|---|---|
0 | all lower | "hello" | HELLO |
1 | mixed | "Hello" | HELLO |
2 | all upper | "HELLO" | HELLO |
当数据以流式传输到行中时, 每个数据都被断言为与它所提供值的列的类型相匹配. 如果任何断言失败, 测试会中止.
重新实现测试函数
现在, 测试函数以如下方式重新实现:
void TestQString::toUpper() { QFETCH(QString, string); QFETCH(QString, result); QCOMPARE(string.toUpper(), result); }
TestQString::toUpper()
函数将执行三次, TestQString::toUpper()
执行的数据是我们在QTestQString::toUpper_data()
函数中关联的数据, 每行数据执行一次.
首先, 我们使用QFETCH()宏获取数据集中的两个元素. QFETCH()需要两个参数: 元素类型和元素名称. 然后, 我们使用QCOMPARE()宏执行测试.
这种方式使得向测试添加新数据变得非常容易, 而无需修改测试本身.
同样, 为了使我们的测试用例成为独立的可执行文件, 需要以下两行:
QTEST_MAIN(TestQString)
#include "testqstring.moc"
和以前一样, QTEST_MAIN() 宏扩展为一个简单的main()方法, 这个方法运行所有测试函数, 并且由于我们的测试类的声明和实现都在 .cpp 文件中, 因此我们还需要包含生成的 moc 文件以使 Qt 的自省工作.
Files: