如何创建数据驱动的测试。
在本章中,我们将演示如何使用不同的测试数据多次执行一个测试。
到目前为止,我们已经将想要测试的数据硬编码到测试函数中。如果我们添加更多的测试数据,函数可能是这样的:
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_data()函数中创建的测试表中的每个条目,执行一次。
首先,我们使用QFETCH()宏获取数据集的两个元素。QFETCH()接受两个参数:元素的数据类型和元素名称。然后,我们使用QCOMPARE()宏执行测试。
这种方法使得在不修改测试本身的情况下向测试添加新数据变得非常容易。
同样,要使我们的测试用例成为一个独立的可执行文件,需要以下两行代码:
QTEST_MAIN(TestQString)
#include "testqstring.moc"
和前面一样,QTEST_MAIN()宏扩展为一个简单的main()方法,它运行所有的测试函数,由于我们的测试类的声明和实现都在一个.cpp文件中,我们还需要包含生成的moc文件,以使Qt的内省工作。
示例项目@ code.qt.io