Введение
Разработка качественного программного обеспечения невозможна без тестирования. В рамках экосистемы Qt предлагается встроенная система модульного тестирования — QTestLib, также известная просто как QTest. Это мощный и легкий инструмент, позволяющий создавать юнит-тесты для C++-приложений, построенных с использованием Qt. Он интегрирован с Qt Creator и может использоваться с системами CI/CD.
В этой статье мы рассмотрим:
- Что такое QTest и зачем он нужен.
- Основы создания тестов.
- Использование различных макросов.
- Проверка GUI и событий.
- Интеграция с
CMakeиqmake. - Практические советы и примеры.
Что такое QTestLib?
QTestLib — это фреймворк для модульного тестирования, входящий в стандартный комплект Qt. Он позволяет:
- Писать автоматические тесты для функций и методов.
- Выполнять параметризованные тесты.
- Проверять корректность работы пользовательских интерфейсов.
- Поддерживать отчёты в разных форматах (XML, Tap, TeamCity и др.).
- Интегрироваться с системами сборки (
qmake,CMake) и CI.
Структура тестов в QTest
Все тесты представляют собой обычные C++ классы, наследующиеся от QObject. Методы тестов — это слоты, которые запускаются фреймворком.
Минимальный пример:
#include <QtTest>
class TestMath : public QObject {
Q_OBJECT
private slots:
void testAddition();
};
void TestMath::testAddition() {
QCOMPARE(2 + 2, 4);
}
QTEST_MAIN(TestMath)
QCOMPARE(actual, expected)— основной макрос для проверки.QTEST_MAINгенерируетmain()и запускает все слоты с тестами.testAddition()— слот, запускаемый QTest.
Основные макросы QTest
| Макрос | Описание |
|---|---|
QCOMPARE(a, b) | Проверяет, равны ли значения a и b. |
QVERIFY(expr) | Проверяет, истинно ли логическое выражение. |
QFAIL(message) | Немедленно проваливает тест. |
QSKIP(message) | Пропускает тест. |
QTEST(actual, type) | Проверяет значение переменной. |
Параметризованные тесты
Вы можете задавать входные данные заранее и тестировать одну и ту же функцию с разными наборами:
class TestPower : public QObject {
Q_OBJECT
private slots:
void testPower_data();
void testPower();
};
void TestPower::testPower_data() {
QTest::addColumn<int>("base");
QTest::addColumn<int>("exp");
QTest::addColumn<int>("result");
QTest::newRow("2^3") << 2 << 3 << 8;
QTest::newRow("3^2") << 3 << 2 << 9;
}
void TestPower::testPower() {
QFETCH(int, base);
QFETCH(int, exp);
QFETCH(int, result);
QCOMPARE(pow(base, exp), result);
}
Тестирование GUI
QTest позволяет симулировать нажатия клавиш, щелчки мыши, перемещения и т.п.:
void TestGui::testButtonClick() {
QPushButton button("Click me");
QSignalSpy spy(&button, &QPushButton::clicked);
QTest::mouseClick(&button, Qt::LeftButton);
QCOMPARE(spy.count(), 1); // проверяем, что сигнал emitted
}
Полезные функции:
QTest::keyClick(widget, Qt::Key_A)QTest::mouseClick(widget, Qt::LeftButton)QTest::qWait(ms)— ожидание в миллисекундах.
Тестирование событий и сигналов
Для тестирования сигналов удобно использовать QSignalSpy:
QSignalSpy spy(myObject, SIGNAL(dataReady(int))); emit myObject->dataReady(42); QCOMPARE(spy.count(), 1); QCOMPARE(spy.at(0).at(0).toInt(), 42);
Интеграция с qmake
Пример .pro файла:
TEMPLATE = app TARGET = testmath CONFIG += qt warn_on console testcase SOURCES += testmath.cpp
Запуск и формат вывода
QTest поддерживает разные форматы вывода:
./testapp -txt # обычный текст ./testapp -xml # XML, удобно для CI ./testapp -tap # Test Anything Protocol
Для фильтрации тестов:
./testapp -functions # список тестов ./testapp -functions | grep login ./testapp testAddition # запуск одного теста
Практические советы
- Разделяйте тесты по модулям: один класс — один модуль.
- Используйте
QSignalSpyдля проверки сигналов. - Не тестируйте сразу много логики в одном тесте.
- Используйте CI-системы для автоматизации (например, GitHub Actions, GitLab CI).
Плюсы QTest
✅ Интеграция с Qt и Qt Creator
✅ Простая и понятная структура
✅ Поддержка GUI и событий
✅ Легко встраивается в существующий проект
✅ Поддержка автоматических отчётов
Минусы QTest
❌ Не поддерживает BDD-подход (как GTest с GMock)
❌ Не самый удобный формат вывода без дополнительной обработки
❌ Ограниченный инструментарий моков (требуется реализация вручную)
Заключение
QTest — это мощный и гибкий инструмент, идеально подходящий для юнит-тестирования Qt-приложений. Он интегрирован с экосистемой Qt, прост в использовании и может применяться как для логических тестов, так и для тестирования интерфейсов.
