我想在ubuntu系统,用QTestLib 做Qt单元测试,请给我一个入门的教程例子
非常好,下面我将为您介绍在 Ubuntu 系统下使用 QTestLib 进行 Qt 单元测试的入门教程。QTestLib 是 Qt 的自带的单元测试框架,完全集成于 Qt 环境中,易于使用。
我们将以 Qt Creator 为例,分为以下几个步骤:
1. 新建 Qt 控制台应用程序
在 Qt Creator 中新建一个 Qt 控制台应用程序项目(不需要 QT5 widgets),选择标准 C++ 项目,在项目中添加自己写的类和函数。
2. 新建测试项目
在同一个 Qt Creator 项目中新建一个 Qt 控制台应用程序项目(不需要 QT5 widgets),选择测试项目。这里生成的测试代码文件是 main.cpp
与 moc_*.cpp
。
3. 测试基础
代码测试通常涉及到以下几个问题:
- 如何确保测试用例的一致性和可重复性?
- 如何设置和清除测试环境?
- 如何捕捉和报告测试失败情况?
QTestLib 框架针对这些问题提供了一些机制:
3.1. 测试用例的一致性
QTestLib 提供了 QTest::qExec()
函数,在其中运行所有的测试用例,如下所示:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyTest test; // 新建测试类
return QTest::qExec(&test, argc, argv); // 运行所有测试用例
}
QTest::qExec()
函数的第一个参数是测试类的指针,指向我们的测试类的对象 test
,第二个和第三个参数是 main()
函数的标准参数。通过 QTest::qExec()
函数,可以运行所有测试用例,并将结果导出到应用程序的标准输出,以便分析和报告。
3.2. 测试环境的设置与清除
QTestLib 可以通过两种方式在测试之前设置和清除测试环境:
- setUp() 和 tearDown() 函数:在测试之前和测试之后,分别设置和清除测试环境。
例如,测试类中定义如下两个测试函数:
class MyTest : public QObject
{
Q_OBJECT
public slots:
void testAddition()
{
...
}
void testSubtraction()
{
...
}
private:
int m_value;
};
我们可以在测试开始前使用 setUp()
函数设置测试环境,在测试结束后使用 tearDown()
函数清除测试环境。如下所示:
class MyTest : public QObject
{
public:
MyTest();
private slots:
void initTestCase(); // 定义测试前的函数
void cleanupTestCase(); // 定义测试结束后的函数
void testAddition();
void testSubtraction();
private:
int m_value;
};
void MyTest::initTestCase()
{
m_value = 0;
}
void MyTest::cleanupTestCase()
{
}
void MyTest::testAddition()
{
m_value = 2 + 2;
QVERIFY(m_value == 4); // 断言,是否为真
}
void MyTest::testSubtraction()
{
m_value = 5 - 3;
QVERIFY(m_value == 2); // 断言,是否为真
}
当测试开始时,QTestLib 将调用 initTestCase()
函数,我们可以在其中设置测试环境。测试结束后,QTestLib 调用 cleanupTestCase()
函数,我们可以在其中清除测试环境。
- 预定义函数:QTestLib 还提供了一些预定义的测试函数,它们在测试开始前或测试结束后执行。
例如,在 main()
函数中,我们可以使用 QTest::qExec()
函数执行测试,同时设置和清除测试环境,如下所示:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
return QTest::qExec(new MyTest, argc, argv);
}
QTest::qExec()
函数的第一个参数是测试类的指针,指向我们的测试类的对象 test
,第二个和第三个参数是 main()
函数的标准参数。通过 QTest::qExec()
函数,可以运行所有测试用例,并将结果导出到应用程序的标准输出,以便分析和报告。
3.3. 测试异常的处理
当测试用例失败时,QTestLib 会抛出异常。我们可以在测试用例内使用以下宏定义来断言测试结果,例如 QVERIFY()
和 QCOMPARE()
:
QVERIFY()
:用于验证一个表达式的结果为 true。QCOMPARE()
:用于验证两个表达式的值相等。
如果表达式的结果为 false 或者两个值不相等,将会抛出 QTest::qFail(const char *message, const char *file, int line)
异常,测试用例失败。
void MyTest::testSubtraction()
{
m_value = 5 - 3;
QVERIFY(m_value == 2); // 断言:m_value 是否等于 2
}
如果断言失败,QTestLib 会输出失败信息,并抛出异常,测试用例失败。
4. 使用 QTestLib 进行测试
下面是一个例子,展示了如何使用 QTestLib 进行简单的测试:
#include <QtTest/QtTest>
#include "mymath.h"
class MyTest : public QObject
{
Q_OBJECT
private slots:
void
可惜没有得到完整,可能超出接口回复文本长度了。
再次提问:
请给出一个例子,展示了如何使用 QTestLib 进行简单的单元测试:
好的,下面是一个使用 QTestLib 进行简单单元测试的例子:
```c++
#include <QtTest>
class TestMath : public QObject
{
Q_OBJECT
public:
TestMath() {}
private slots:
void testAddition()
{
int result = 1 + 2;
QVERIFY(result == 3);
}
void testSubtraction()
{
int result = 5 - 3;
QCOMPARE(result, 2);
}
void testMultiplication()
{
int result = 4 * 2;
QVERIFY2(result == 8, "Failed: result is not equal to 8");
}
};
QTEST_APPLESS_MAIN(TestMath)
#include "testmath.moc"
在这个例子中,我们创建了一个名为 TestMath 的测试类,并在其中声明了三个测试函数:testAddition、testSubtraction 和 testMultiplication。在每个测试函数中,我们执行一些计算,并使用 QVERIFY、QVERIFY2 和 QCOMPARE 宏来验证结果是否正确。
QVERIFY 和 QVERIFY2 宏会分别判断一个表达式是否为真,如果为假则测试失败并输出一条错误消息。而 QCOMPARE 宏则比较两个表达式的值是否相等,如果不相等则测试失败并输出一条错误消息。
最后,我们使用 QTEST_APPLESS_MAIN 宏来定义测试应用程序的入口点,并引入testmath.moc文件以支持使用QObject的测试类。
以下是使用 QTestLib 进行简单的单元测试的示例代码。
1. 创建工程
首先,打开 Qt Creator,创建一个新的 Qt 控制台应用程序工程:选择 “File” > “New File or Project”,选择 “Non-Qt Project” > “Plain C++ Project”,输入名称、工程路径和某个可用的编译器,再单击 “Next”。
在 “Kit Selection” 页面,选择 “Desktop Qt 5.x.x GCC 64-bit” 或任何可用的 Qt 5 Kit,然后单击 “Next”。
在 “Project Management” 页面,将 “Create Main Function” 选项取消勾选,输入 “TestProject” 名称,然后单击 “Next”。
在 “Project Configuration” 页面,选择 “None” 作为 “Version Control”,然后单击 “Finish”。
此时,工程已经创建成功了。
2. 添加 QTestLib 库
在工程的
TestProject.pro
文件中,添加以下行:QT += testlib CONFIG += console
这将包含 QTest 类以及与应用一起使用的测试库依赖。
3. 编写测试用例
在 “Project” 文件夹下创建一个新的源文件
testexample.cpp
,编写测试用例。以下是一个例子:#include <QtTest/QtTest> // 这个单元测试将测试 int 是否相等 class TestExample : public QObject { Q_OBJECT private slots: void simpleTest() { int x = 1; QCOMPARE(x, 1); // 期望 x 值为 1 } void nullTest() { void* p = 0; QVERIFY(!p); // 期望 p 值为 0 } };
如您所见,这里定义了一个
TestExample
类,它包含了两个测试用例:第一个测试用例检查x
是否等于1
,第二个测试用例检查一个指针是否为空。使用 QTest 宏
QCOMPARE
和QVERIFY
来比较结果。4. 激活自动测试
QTest 使用一个宏
QTEST_APPLESS_MAIN
来自动运行测试用例。只需要创建一个 “main.cpp” 文件,并使用以下代码激活宏。#include <QTest> QTEST_APPLESS_MAIN(TestExample)
此时,便可以在 Qt Creator 的 “Compile Output” 面板中,找到文本 “PASS:2 测试”。这表示两个测试用例已成功通过。
如果某个测试用例未成功通过,则在 Qt Creator 中的 “Compile Output” 面板 中,您可以找到更多信息。
以下是一个使用 QTestLib 进行简单测试的例子。
假设我们有一个简单的计算器程序,使用 QTestLib 进行测试。
1. 编写测试用例
创建一个名为
CalculatorTest.h
的文件,编写测试用例。以下是一个例子:#include <QtTest/QtTest> #include "Calculator.h" class CalculatorTest : public QObject { Q_OBJECT private slots: void testAddition(); void testSubtraction(); void testMultiplication(); void testDivision_data(); void testDivision(); }; void CalculatorTest::testAddition() { Calculator calculator; QCOMPARE(calculator.addition(2, 2), 4); QCOMPARE(calculator.addition(0, 0), 0); QCOMPARE(calculator.addition(-1, 1), 0); } void CalculatorTest::testSubtraction() { Calculator calculator; QCOMPARE(calculator.subtraction(2, 2), 0); QCOMPARE(calculator.subtraction(0, 0), 0); QCOMPARE(calculator.subtraction(-1, 1), -2); } void CalculatorTest::testMultiplication() { Calculator calculator; QCOMPARE(calculator.multiplication(2, 2), 4); QCOMPARE(calculator.multiplication(0, 0), 0); QCOMPARE(calculator.multiplication(-1, 1), -1); } void CalculatorTest::testDivision_data() { QTest::addColumn<int>("nominator"); QTest::addColumn<int>("denominator"); QTest::addColumn<int>("quotient"); QTest::addColumn<bool>("exception"); QTest::newRow("Valid case 1") << 4 << 2 << 2 << false; QTest::newRow("Valid case 2") << 0 << 4 << 0 << false; QTest::newRow("Valid case 3") << 1 << -1 << -1 << false; QTest::newRow("Invalid case") << 4 << 0 << 0 << true; } void CalculatorTest::testDivision() { Calculator calculator; QFETCH(int, nominator); QFETCH(int, denominator); QFETCH(int, quotient); QFETCH(bool, exception); if (exception) { QVERIFY_EXCEPTION_THROWN(calculator.division(nominator, denominator), std::runtime_error); } else { QCOMPARE(calculator.division(nominator, denominator), quotient); } } QTEST_APPLESS_MAIN(CalculatorTest) #include "CalculatorTest.moc"
每个测试用例都是
void
函数,我们使用的是QCOMPARE()
宏进行判断实际输出的值与预期相比是否一致。在上述代码中,我们使用了
Q_TEST_MAIN
宏,表示不需要自动生成 main 函数,并传入了测试类名称CalculatorTest
,同时还用到了数据驱动的方式(testDivision_data()
和testDivision()
函数)来完成涉及多个数据集的测试。2. 编译和运行测试
在命令行中,进入工程根目录,输入以下命令进行编译:
qmake -project qmake make
在命令行中,输入以下命令运行测试:
./CalculatorTest
在命令行中,你可以看到类似以下的输出结果:
********* Start testing of CalculatorTest ********* Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 8.3.0) PASS : CalculatorTest::initTestCase() PASS : CalculatorTest::testAddition() PASS : CalculatorTest::testDivision("Invalid case") PASS : CalculatorTest::testDivision("Valid case 1") PASS : CalculatorTest::testDivision("Valid case 2") PASS : CalculatorTest::testDivision("Valid case 3") PASS : CalculatorTest::testMultiplication() PASS : CalculatorTest::testSubtraction() PASS : CalculatorTest::cleanupTestCase() Totals: 9 passed, 0 failed, 0 skipped, 0 blacklisted, 37ms ********* Finished testing of CalculatorTest *********
以上就是使用 QTestLib 进行简单测试的例子。如果您有其他问题或疑问,欢迎随时提出。
版权归原作者 零点零一 所有, 如有侵权,请联系我们删除。