> 文章列表 > 在ubuntu系统,用QTestLib 做Qt单元测试,请给我一个入门的教程例子

在ubuntu系统,用QTestLib 做Qt单元测试,请给我一个入门的教程例子

在ubuntu系统,用QTestLib 做Qt单元测试,请给我一个入门的教程例子

我想在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_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” 文件,并使用以下代码激活宏。

```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 进行简单测试的例子。如果您有其他问题或疑问,欢迎随时提出。