Here is the directory structure I used:
project.pro - src/main.cpp - src/module/implementation.cpp - src/module/implementation.h - tests/testmain.cpp - tests/module/testimplementation.cpp - tests/module/testimplementation.h
Optimally when developing and running the application, I'd want the workflow to be:
- Compile the program. Continue if successful.
- Compile the unit tests. Continue if successful.
- Run the unit tests against the program
- If unit tests fail, abort and display the errors
- If unit tests succeed, create the application package (but without the unit test code), deploy it and run)
I didn't want to use that much time into setting up the project and working out the kinks, so I settled for something simpler. If I want to run unit tests, I compile the application and the unit test files, but I exclude the application's main.cpp. Instead I include testmain.cpp which creates the unit test cases to run. If I want to run the application properly I just compile the application files without the unit test files. Whether to run the unit tests version is controlled from the project file with one CONFIG line. This removes some of the advantages of unit tests, as I have to remember to run the unit tests myself every once in a while to make sure nothing broke. But for me it's a good compromise for small and simple projects as I can use the project pretty much as it was created by QtCreator.
In my project.pro I have a line to switch between running unit tests or the proper application. This switch actually instructs the build system to include Qt Testing Library, but I use it as a trigger to switch between the unit test version and normal application version.
# Uncomment if just unit tests are to be ran. # CONFIG += qtestlibTo run the unit tests instead of the main application, add after OTHER_FILES in project.pro rules to remove the main application's main.cpp and instead include the unit test's testmain.cpp. Also, the unit test sources are added here. Here's example from above directory structure:
qtestlib { # If qtestlib is in CONFIG, replace application's main.cpp # with unit test main. Also add unit test sources. SOURCES -= src/main.cpp SOURCES += tests/testmain.cpp \ tests/module/testimplementation.cpp HEADERS += tests/logic/testimplementation.h }The default QtTest framework is a bit cumbersome in my opinion. It basically assumes that you have one executable for each test. I like to run all tests from the same tester. So that's why I have the testmain.cpp there. It contains the code to run all the tests. In the example it contains only the code to test the class "Implementation", but it's easy to add more tests there. Here's an example of it:
tests/testmain.cpp:
#includeA skeleton of the TestImplementation class that tests the Implementation class could be like: tests/module/testimplementation.h#include "module/testimplementation.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); int retval(0); retval += QTest::qExec(&TestImplementation(), argc, argv); // Add more test like above here return (retval ? 1 : 0); }
#ifndef TESTIMPLEMENTATION_H #define TESTIMPLEMENTATION_H #includetests/module/testimplementation.h#include "../../src/module/implementation.h" class TestImplementation : public QObject { Q_OBJECT private slots: void dummyTest(); }; #endif // TESTIMPLEMENTATION_H
void TestImplementation::dummyTest() { // Always succeeds QVERIFY(true); }