我想在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()`函数,在其中运行所有的测试用例,如下所示:
```cpp
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() 函数:在测试之前和测试之后,分别设置和清除测试环境。
例如,测试类中定义如下两个测试函数:
```cpp
class MyTest : public QObject
{
Q_OBJECT
public slots:
void testAddition()
{
...
}
void testSubtraction()
{
...
}
private:
int m_value;
};
```
我们可以在测试开始前使用 `setUp()` 函数设置测试环境,在测试结束后使用 `tearDown()` 函数清除测试环境。如下所示:
```cpp
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()` 函数执行测试,同时设置和清除测试环境,如下所示:
```cpp
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)` 异常,测试用例失败。
```cpp
void MyTest::testSubtraction()
{
m_value = 5 - 3;
QVERIFY(m_value == 2); // 断言:m_value 是否等于 2
}
```
如果断言失败,QTestLib 会输出失败信息,并抛出异常,测试用例失败。
## 4. 使用 QTestLib 进行测试
下面是一个例子,展示了如何使用 QTestLib 进行简单的测试:
```cpp
#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` 文件中,添加以下行:
```pro
QT += testlib
CONFIG += console
```这将包含 QTest 类以及与应用一起使用的测试库依赖。
## 3. 编写测试用例
在 “Project” 文件夹下创建一个新的源文件 `testexample.cpp` ,编写测试用例。以下是一个例子:
```cpp
#include <QtTest/QtTest>// 这个单元测试将测试 int 是否相等
class TestExample : public QObject
{
Q_OBJECTprivate 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” 文件,并使用以下代码激活宏。
```cpp
#include <QTest>QTEST_APPLESS_MAIN(TestExample)
```此时,便可以在 Qt Creator 的 “Compile Output” 面板中,找到文本 “PASS:2 测试”。这表示两个测试用例已成功通过。
如果某个测试用例未成功通过,则在 Qt Creator 中的 “Compile Output” 面板 中,您可以找到更多信息。
以下是一个使用 QTestLib 进行简单测试的例子。
假设我们有一个简单的计算器程序,使用 QTestLib 进行测试。
## 1. 编写测试用例
创建一个名为 `CalculatorTest.h` 的文件,编写测试用例。以下是一个例子:
```cpp
#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. 编译和运行测试
在命令行中,进入工程根目录,输入以下命令进行编译:
```bash
qmake -project
qmake
make
```在命令行中,输入以下命令运行测试:
```bash
./CalculatorTest
```在命令行中,你可以看到类似以下的输出结果:
```bash
********* 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 进行简单测试的例子。如果您有其他问题或疑问,欢迎随时提出。