How to add tests to an existing project?
-
Hi,
I would like to use Qt test or google test.
How does the folder structure look when a test is added to an existing project/ repository?
Do I just add a new Auto test project?
Are there any tutorials/ YouTube videos that explain the process of adding Qt tests/ google test to a Qt project using Qt Creator? -
@jkwok678 said in How to add tests to an existing project?:
E.g. All of the unit tests or just 1 of them ?
Is it doable like Java and Junit in the Intelij IDE?In Qt Creator in the top left corner expand the combobox that says "projects" and select tests to run them
What I mean is that the IDE has good support for JUnit, where I can click a button close to where I set breakpoints and run that particular test.
No as far as I'm aware
It seems a little messy in terms of project structure to have 1 auto test project for each class/file?
Is the 2nd way of doing things better?Qt Test is designed to be used 1-project-per-test. You can build around it but, believe me, the results are sub-par.
But when I tried to create mutltiple test projects, it's more like
MyProject/tests/QtTests/WidowClassTest
MyProject/tests/QtTests/CanvasClassTest
MyProject/tests/QtTests/MapClassTestFolder structure has nothing to do with projects.
To test classesWindow
,Canvas
andMap
, you can create a folder structure like:- MyProject
- tests
- tst_window.cpp
- tst_canvas.cpp
- tst_map.cpp
- CMakeLists.txt
- tests
and the content of CMakeLists.txt would be:
cmake_minimum_required(VERSION 3.9) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test Gui Widgets REQUIRED) macro(BasicTest TestName) set(targetName "tst_${TestName}") set(testProjectName "tst${TestName}") string(TOLOWER ${TestName} TestSourceFileName) add_executable(${targetName} "tst_${TestSourceFileName}.cpp") target_include_directories(${targetName} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(${targetName} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets) set_target_properties(${targetName} PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON ) add_test(NAME ${testProjectName} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" COMMAND $<TARGET_FILE:${targetName}>) endmacro() BasicTest(Window) BasicTest(Canvas) BasicTest(Map)
To add more tests just add 1 line at the end
- MyProject
-
Hi,
Depending on how the project is structured you may have to move some stuff aground.
In any case, there's often a dedicated tests subfolder than will contain more subfolders to keep your test code cleanly separated.
-
Should I be adding the test code to my current classes?
Or should I be using the autotest project?
If I wanted to test my Window class method called convertMilesToMetres, should I do it this way with an auto test project?#include "window.h class WindowTest: public QObject { Q_OBJECT private: private slots: void initTestCase() { Window win = new Window; } void testConverter() { QCOMPARE(win.convertMilesToMetres(1), 1600); // compare two values } }; QTEST_MAIN(WindowTest) #include "windowtest.moc"
-
@jkwok678 said in How to add tests to an existing project?:
Should I be adding the test code to my current classes?
No, generally it's a bad idea. You could add special members that are needed for tests (e.g. getter methods for intermediate results you want to test) inside
#ifdef
blocks so you can exclude them in the deployed buildsOr should I be using the autotest project?
Yes, even more than one
If I wanted to test my Window class method called convertMilesToMetres, should I do it this way with an auto test project?
There is nothing magical inside tests, they are just normal C++ functions, treat them as such:
#include "window.h" class WindowTest : public QObject { Q_OBJECT private slots: void testConverter() { Window win; QCOMPARE(win.convertMilesToMetres(1), 1600); // compare two values } }; QTEST_MAIN(WindowTest) #include "windowtest.moc"
-
@VRonin
Even with this example.
If I make a new Auto test project with thisThere is nothing magical inside tests, they are just normal C++ functions, treat them as such: #include "window.h" class WindowTest : public QObject { Q_OBJECT private slots: void testConverter() { Window win; QCOMPARE(win.convertMilesToMetres(1), 1600); // compare two values } }; QTEST_MAIN(WindowTest) #include "windowtest.moc"
How can I run it with Cmake on build?
Also does it make sense to maybe not make a auto test poject, and just create a .cpp file with the exact same methods inside instead?
-
@jkwok678 said in How to add tests to an existing project?:
How can I run it with Cmake on build?
You don't run autotests on build but afterwards with e.g. 'make test' or in a jenkins job.
See also CMake documentation about add_test() -
@Christian-Ehrlicher
Hmm, so what exactly would I need to start automated testing?
Coming from a Java and JUnit background, all I had to do was make a test class, and I could create a test configuration and run that and all the tests in the test class would run whenever I liked. Is this possible with Qt Test? -
If your are using CMake, the workflow is:
- call
cmake
- this crates the makefile/projectfile that the compiler/linker can digest
- call
make
(cmake --build .
for convenience)- to actually build the projects
- call
ctest
- this will run the tests that you added with
add_test()
. You can run specific tests by specifying the-r name_of_the_test
argument
- this will run the tests that you added with
- call
-
@VRonin
Am I able to run any test I want at any time?
E.g. All of the unit tests or just 1 of them ?
Is it doable like Java and Junit in the Intelij IDE?
What I mean is that the IDE has good support for JUnit, where I can click a button close to where I set breakpoints and run that particular test.
Also would just 1 test project be enough be multiple cpp test files?
It seems a little messy in terms of project structure to have 1 auto test project for each class/file?I imagined my test structure to be a little like
MyProject/tests/QtTests/
And inside here I can have a
windowTest.cpp
,canvasTest.cpp
andmapTest.cpp
. Along with aCMakeLists.txt
.
But when I tried to create mutltiple test projects, it's more likeMyProject/tests/QtTests/WidowClassTest MyProject/tests/QtTests/CanvasClassTest MyProject/tests/QtTests/MapClassTest
Each with their own
___Test.cpp
and aCMakeLists.txt
.
Is the 2nd way of doing things better? -
@jkwok678 said in How to add tests to an existing project?:
E.g. All of the unit tests or just 1 of them ?
Is it doable like Java and Junit in the Intelij IDE?In Qt Creator in the top left corner expand the combobox that says "projects" and select tests to run them
What I mean is that the IDE has good support for JUnit, where I can click a button close to where I set breakpoints and run that particular test.
No as far as I'm aware
It seems a little messy in terms of project structure to have 1 auto test project for each class/file?
Is the 2nd way of doing things better?Qt Test is designed to be used 1-project-per-test. You can build around it but, believe me, the results are sub-par.
But when I tried to create mutltiple test projects, it's more like
MyProject/tests/QtTests/WidowClassTest
MyProject/tests/QtTests/CanvasClassTest
MyProject/tests/QtTests/MapClassTestFolder structure has nothing to do with projects.
To test classesWindow
,Canvas
andMap
, you can create a folder structure like:- MyProject
- tests
- tst_window.cpp
- tst_canvas.cpp
- tst_map.cpp
- CMakeLists.txt
- tests
and the content of CMakeLists.txt would be:
cmake_minimum_required(VERSION 3.9) find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Test REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Test Gui Widgets REQUIRED) macro(BasicTest TestName) set(targetName "tst_${TestName}") set(testProjectName "tst${TestName}") string(TOLOWER ${TestName} TestSourceFileName) add_executable(${targetName} "tst_${TestSourceFileName}.cpp") target_include_directories(${targetName} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(${targetName} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Test Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets) set_target_properties(${targetName} PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON ) add_test(NAME ${testProjectName} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" COMMAND $<TARGET_FILE:${targetName}>) endmacro() BasicTest(Window) BasicTest(Canvas) BasicTest(Map)
To add more tests just add 1 line at the end
- MyProject
-
@jkwok678 said in How to add tests to an existing project?:
What's that?
BasicTest
is the macro defined in the code snippet@VRonin said in How to add tests to an existing project?:
To test classes
Window
,Canvas
andMap
-
@jkwok678 said in How to add tests to an existing project?:
So is what you said earlier, with 1 test project, and 3 test files optimal?
This is not 1 test project. 1 CMakeLists.txt can create multiple projects, in this case I'm creating 1 project for each class to test, I'm just doing it in a single CMakeLists.txt file
-
@jkwok678 said in How to add tests to an existing project?:
So everytime I want to test another class, I should create a new autotest project with Qt Creator?
No. Say you now want to test the class
MyClass
. You'd add the fileMyProject/tests/tst_myclass.cpp
and appendBasicTest(MyClass)
to the snippet pasted above -
@jkwok678 Conceptually yes (Stackoverflow would say no because the technical terms you used are not very precise but high-level you got the concept)
P.S.
If you don't want unnecessary pain in the future with cross-platform support, keep your .c/.cpp/.h,/.hpp etc files lower-case only