Unit Testing with multiple .cpp files
-
Hello all,
I'm new to programming / QT and am trying to implement unit tests for my application. The application will have multiple classes and I would like to write unit tests to pair with these classes as well as the project as a whole. Looking at the forums and GPT example code, I understand I should have my project built like so:
Project.pro Headers --mainwindow.h --src/ ----class1.h ----class2.h Sources --mainwindow.cpp --main.cpp --src/ ----class1.h ----class2.h Forms --mainwindow.ui Other files --tests/ ----tst_class1 ----tst_class2 ----tst_class1and2
With my .pro file containing:
QT += core gui testlib CONFIG += c++17 testcase SOURCES += \ main.cpp \ mainwindow.cpp \ src/class1.cpp \ src/class2.cpp \ HEADERS += \ mainwindow.h \ src/class1.h \ src/class2.h \ FORMS += \ mainwindow.ui # Test sources test1.sources = tests/tst_class1.cpp test1.target = tst_class1 test1.CONFIG += console test1.CONFIG += testcase test2.sources = tests/tst_class2.cpp test2.target = tst_class2 test2.CONFIG += console test2.CONFIG += testcase test3.sources = tests/tst_class1and2.cpp test3.target = tst_class1and2 test3.CONFIG += console test3.CONFIG += testcase # Include the test sources in the project OTHER_FILES += \ tests/tst_class1.cpp \ tests/tst_class2.cpp \ tests/tst_class1and2.cpp # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target DISTFILES +=
I have each tst file containing
#include <QtTest> #include "src/class1.h" class TestStateMachine : public QObject { Q_OBJECT private slots: void initTestCase(); void test1A(); void test1B(); void cleanupTestCase(); }; [function definitions here] QTEST_MAIN(TestStateMachine) #include "tst_main.moc"
If possible there are two things I'd like to fix.
-
Most important although the program compiles, I understand that I'm supposed to see tst_class1.exe in my build folder and I do not, so I have no idea if the tests are being run or how to run them
-
I know QT has the display window "8 Test Results," with output that the provided example uses. Looking at help documents from ~2019, it looks like this won't populate if you have multiple test files (or the only way to have multiple test files subverts this window.) Is that still the case?
-
-
Hi,
That is usually done using the SUBDIRS template where each test is its own project as is the application.
Often you will have a library project that contains your application business logic and that will also contain the tests and an app project that will make use of the library.
-
@SGaist Fantastic! Thank you for letting me know. I'm looking at the wiki here (https://wiki.qt.io/SUBDIRS_-_handling_dependencies) and seeing the example:
/FooApp |--- Makefile |--- subdirs.pro |--- src | |--- app | |--- app.pro | |--- Makefile | |--- Makefile.Debug | |--- Makefile.Release | `--- ... (source files of app) |--- lib | |--- lib.pro | |--- Makefile | |--- Makefile.Debug | |--- Makefile.Release | `--- ... (source files of lib) |--- lib2 | |--- lib2.pro | |--- Makefile | |--- Makefile.Debug | |--- Makefile.Release
For my project, would that then translate to?
/FooApp |--- Makefile |--- subdirs.pro |--- src | |--- app | |--- app.pro | |--- mainwindow.h | |--- mainwindow.cpp | |--- main.cpp | |--- tst_class1and2 |--- class 1 | |--- class1.pro | |--- class1.h | |--- class1.cpp | |--- tst_class1.cpp |--- class2 | |--- class2.pro | |--- class2.h | |--- class2.cpp | |--- tst_class2.cpp
-
It would rather be something like:
/FooApp |--- subdirs.pro |--- src | |--- app | |--- app.pro | |--- appname | |--- appname.pro | |--- mainwindow.h | |--- mainwindow.cpp | |--- main.cpp | |--- tests | |--- tests.pro | |--- tst_mainwindow | |--- tst_mainwindow.pro | |--- tst_mainwindow.cpp |--- lib | |--- lib.pro |. |--- mylib |. |--- mylib.pro | |--- class1.h | |--- class1.cpp | |--- class2.h | |--- class2.cpp | |--- tests | |--- tests.pro | |--- tst_class1 | |--- tst_class1.pro | |--- tst_class1.cpp | |--- tst_class2 | |--- tst_class2.pro | |--- tst_class2.cpp
You can check the Qt sources structure to make yourself an idea.
Note that since it's a new project, you might want to move to cmake as qmake is deprecated.
-
The "folders" .pro files are subdirs projects while the leaf .pro files are either app, libs or tests projects.
-
Ok, with this structure I'm trying to build my tests/tst_class1/tst_class1.cpp However, I'm doing something wrong as my code is producing an unresolved external symbol error. I'm guessing I'm doing something wrong in the pro files.
lib.pro
TEMPLATE = subdirs SUBDIRS += \ mylib \ tests
mylib.pro
QT += core gui sql network CONFIG += c++17 cmdline testcase # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ class1.cpp \ main.cpp HEADERS += \ class1.h # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
tests.pro
TEMPLATE = subdirs SUBDIRS += \ tst_class1
tst_class1.pro
QT += core gui sql network testlib CONFIG += c++17 cmdline testcase # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ tst_class1.cpp \ INCLUDEPATH += ../../mylib/ # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
Is there something I need to change?
-
You are not linking against the library you are testing.