Unit Tests для проекта из одного класса
У меня есть проект Qt widgets и я хочу создать тесты для нескольких функций (MainWindow::RPN). Как это сделать через Qt Creator? Ну или как перенести проект на vs и сделать там? Я перепробовал все что смог нагуглить (и оф документацию, и с хабара).
#.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
RC_FILE = CalculatorIco.rc
CONFIG(testcase) {
QT += testlib
HEADERS += \
testtest.h
SOURCES += \
test_main.cpp\
testtest.cpp
}
else {
SOURCES += \
main.cpp
}
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
testtests.cpp
//testtests.cpp
#include "testtest.h"
#include "mainwindow.h"
#include <QtTest>
TestTests::TestTests(QObject *parent) : QObject(parent)
{
}
void TestTests::first_test()
{
MainWindow w;
QString tempString = "2 + 2.2";
QVERIFY(w.RPN(tempString) == 4.2);
}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
double RPN(QString inString);
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
/*...*/
double RPN(QString inQString) {
/*...*/
}
Тестовые файлы почти полностью копируют пример выше.
Ответы (1 шт):
Qt Test можно использовать и в одиночном проекте, но для этого нужно настроить дополнительные конфигурации сборки.
В файле проекта настраиваем, что собирать и запускать(приложение или тесты) и какие исходники при этом используются.
У меня получился следующий файл проекта:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
#
# Main Sources
#
SOURCES += \
mainwindow.cxx
HEADERS += \
mainwindow.hxx
FORMS += \
mainwindow.ui
#
# Выбор исходников и параметров для сборки
#
CONFIG(testcase) {
#
# для сборки тестов
#
QT += testlib
HEADERS += \
testtests.hxx
SOURCES += \
test_main.cxx\
testtests.cxx
} else {
#
# для сборки приложения
#
SOURCES += \
main.cxx
}
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
То есть я создал отдельный main и добавил класс для тестов
Содержимое файлов:
//test_main.cxx
#include "testtests.hxx"
#include <QtTest>
QTEST_MAIN(TestTests)
//testtests.hxx
#ifndef TESTTESTS_HXX
#define TESTTESTS_HXX
#include <QObject>
class TestTests : public QObject
{
Q_OBJECT
public:
explicit TestTests(QObject *parent = nullptr);
private slots:
void first_test();
};
#endif // TESTTESTS_HXX
//testtests.cxx
#include "testtests.hxx"
#include "mainwindow.hxx"
#include <QtTest>
TestTests::TestTests(QObject *parent) : QObject(parent)
{
}
void TestTests::first_test()
{
MainWindow w;
QVERIFY(true);
}
Тесты собираются при условии, что переменная CONFIG содержит testcase, иначе приложение
Теперь идем в конфигурацию проекта в Qt Creator и добавляем параметры сборки:
- Жмем "добавить", выбираем тип и вводим название(можно скопировать и переименовать имеющиеся)
- Правим "Основное - каталог сборки"
- Разворачиваем "Сборка, этапы - qmake"
- в поле "дополнительные параметры" вводим
CONFIG+=testcase
Можно попробовать собрать и запустить тесты
Добавим тест для какой либо логики из MainWindow
void TestTests::second_test()
{
MainWindow w;
QString test{QString::fromUtf8("demo")};
QCOMPARE(w.someMetod(test), test.size());
}
Дополнение
то появляются две ошибки: undefined reference to `MainWindow::RPN(QString)' и error: ld returned 1 exit status.
У вас в заголовочном файле RPN объявлена как метод класса MainWindow
А в файле реализации(cpp) как простая функция
При вызове в тесте вы используете RPN как метод. Но тело метода не определено.
Решение:
Так как RPN не зависит от приватных полей класса MainWindow, то можно сделать ее свободной функцией, что так же облегчит ее тестирование(не нужно создавать объект класса)
Для этого в файле mainwindow.h вынесите ее за пределы объявления класса:
double RPN(QString inString);
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
// double RPN(QString inString);
В файле теста замените вызовы метода на вызов функции
void TestTests::first_test()
{
// MainWindow w;
QString tempString = "2 + 2.2";
QVERIFY(/* w. */RPN(tempString) == 4.2);
}
P.S.: для сравнений двух значений лучше использовать QCOMPARE


