How to structure project while unit-testing Qt app by QTestLib

I got my Qt project and I'm using Qt Creator. I want to unit-test all my code. However I'm quite new at QTestLib framework but everyone recommended it for testing Qt-based source. Now I'm a little confused how to structure test project with app project.

  1. Can I put all source and testing code in same project? If so, how could I manage them? I didn't find any option that let me start app or start test in one project.
  2. If I put app source and testing code in separate projects, the testing project will reference app project, that's not quite convenient.
  3. For lots for classes required to be tested, how do I manage testing code?

How do you guys manage testing code in such a situation? Thanks.

Answers


First structure source like below:

MyApp
MyAppUnitTest

Under MyApp project, use a MyAppSrc.pri to locate source files:

SOURCES += \
    ../../../framework/src/myapp.cpp \
    ../../../framework/src/mycontrol.cpp

HEADERS += \
    ../../../framework/inc/myapp.h \
    ../../../framework/inc/mycontrol.h

INCLUDEPATH += ../../../framework/extlibs

Include this .pri in MyApp.pro like:

include(MyAppSrc.pri)

Then structure the testing project exactly like the main project, with one extra include in MyAppUnitTest.pro:

include(MyAppUnitTestSrc.pri)
include(../MyApp/MyAppSrc.pri)

I use this approach: http://xilexio.org/?p=125

Namely, place a test config in the single .pro file that builds everything. File hierarchy:

myproject.pro
src/
    Example1.cpp
    Example2.cpp
    Example1.h
    Example2.h
test/
    ExampleTest.cpp
    ExampleTest.h

myproject.pro file:

QT += #needed modules

CONFIG += qt c++11

HEADERS += \
    src/Example1.h \
    src/Example2.h

SOURCES += \
    src/Example1.h \
    src/Example2.h

test{
    message(Configuring test build...)

    TEMPLATE = app
    TARGET = myapptests

    QT += testlib

    HEADERS += \
        test/ExampleTest.h

    SOURCES += \
        test/ExampleTest.cpp
}
else{
    TEMPLATE = lib
    TARGET = myapp

    CONFIG += plugin

    TARGET = $$qtLibraryTarget($$TARGET)
}

In my example, I'm building a plugin library, but the method should work for an app as well. In the case of an app, it is likely that SOURCES -= src/main.cpp is needed under the else clause, plugin libraries don't have it. If this is not done, the main() of the app will clash with the main() of the unit tests.

ExampleTest.cpp looks like the following:

#include "ExampleTest.h"

void ExampleTest::exampleTest(){
    //Do the tests
}

QTEST_MAIN(ExampleTest)

ExampleTest.h looks like the following:

#include <QtTest/QtTest>

class ExampleTest : public QObject {
Q_OBJECT

private slots:
    void exampleTest();
};

To build the project tests, in a separate directory than the regular build, run:

qmake path/to/myproject.pro "CONFIG += test"

I like the other answers but I would like to also give some feedback how we do this at the company I currently work for:

  1. Create a subdirs project (this will be the top-level project that will manage ALL including your library project or whatever you want to test)

    +-----MyProject (top-level subdirs)
    
  2. Add your library projects as a sub-project

    +-----MyProject (top-level subdirs)
              |
              +-----Library (library project, UI project etc.)
    
  3. Add another subdirs projects (for the tests)

    +-----MyProject (top-level subdirs)
              |
              +-----Library (library project, UI project etc.)
              |
              +-----Tests (subdirs for tests)
    
  4. Create a QUnitTest project an add it to the testing subdirs project

    +-----MyProject (subdirs)
              |
              +-----Library (library project, UI project etc.)
              |
              +-----Tests (subdirs for tests)
                      |
                      +----- TestA (QUnitTest project for testing feature A)
    
  5. Add as many tests as you see fit

             ...
              |
              +-----Tests (subdirs for test)
                      |
                      +----- TestA (QUnitTest project for testing feature A)
                      |
                      +----- TestB (QUnitTest project for testing feature B)
                      |
                      +----- TestC (QUnitTest project for testing feature C)
                      |
                     ...
                      |
                      +----- TestZ (QUnitTest project for testing feature Z)
    

If you need to group test in groups you can also use subdirs to do that. subdirs also ensures creating of real directories in your file system. If you want to avoid too much subdirsing you can group the tests in folders that you have created on your own in your filesystem inside the Tests project folder.

Beside that I would also recommend to add a subdirs for template projects.

+-----MyProject (subdirs)
          |
          +-----Library (library project, UI project etc.)
          |
          +-----Tests (subdirs for tests)
          |           |
          |          ...
          |
          +-----Templates (subdirs for template projects
                      |
                      +----- TemplateA (template project for feature A)
                      |
                      +----- TemplateB (template project for feature B)
                      |
                      +----- TemplateAB (template project for feature A and B together)
                      |
                     ...
                      |
                      +----- TemplateZ (template project for feature Z)

This is of course based on your library's functionality. With template projects I mean custom widgets etc. that link against your library and expose selectively (or all) of its functionality in the way it's supposed to appear to the user. For example if you have a library that manages various camera devices you can create a template project for each camera device thus allowing for the users of your library to just copy-paste the specific template project and expand it or at least see how the integration of your library is supposed to happen in general. This allows reducing the documentation and at the same time giving nice self-contained examples that should reduce the development time that is otherwise spent in figuring out how the integration and usage of the library works (you can say it's sort of a set of Hello World projects :)). Last but not least you can outline solutions for different use-cases.


I use Qt Creator by CMake instead of qmake to build my Qt project.

Basically I have to folders:

src
tests

Each test is a program in itself testing a class. The app to be tested is compiled as a library.. You compile all your sources in the folder src as a library.

// ClassTest.cpp
#include "ClassTest.h"
#include "Class2Test.h" // Class of the app

#include <QtTest/QtTest>

ClassTest::ClassTest( QObject* parent )
    : QObject(parent)
{ 
}

QTEST_MAIN( ClassTest )
#include "ClassTest.moc"

You just have to link your lib to your test executable.

Example:

in the src folder CMakeLists.txt example

add_library( MyAPP
    SHARED
    Class2Test.cpp
)
target_link_libraries( MyAPP
    ${QT_LIBRARIES}
)

in the tests folder CMakeLists.txt example, for each test.

qt4_automoc( ${test_src} )
add_executable( ${test_name} ${test_src} )
target_link_libraries( ${test_name}
    MyAPP
    ${QT_LIBRARIES}
    ${QT_QTTEST_LIBRARY}
)

It is still in the same project but you can add a flag to let the user compile the test or not. It is clean because the app stays untouched and it allows you to test each class of your app.


Need Your Help

Python: Best Way to Exchange Keys with Values in a Dictionary?

python dictionary

I receive a dictionary as input, and would like to to return a dictionary whose keys will be the input's values and whose value will be the corresponding input keys. Values are unique.