[SOLVED] QTest an subprojects: How to link against application with "TEMPLATE = app" configuration?



  • Hi :)

    I'm currently trying to make Unit-Testing (QTest) work in my project. I took "this ":https://gitorious.org/qwebservice/qwebservice/source project as an reference on how I could struture the whole thing.

    However, I've been trying to find a solution for a "undefined reference"-error for hours now. Anyway, let me first describe what my project looks like now:

    This is my current filestructure (please note that my project is a lot bigger, but these are the essential parts):

    @
    MyApp
    |
    | buildInfo.pri (A)
    | libraryIncludes.pri (B)
    | MyApp.pro (C)
    |
    +---build
    | +---src
    | ---tests
    |
    +---MyApp
    | | MyApp.pro (D)
    | | deployment.pri
    | | inputvectors.h (E)
    | | inputvectors.cpp (F)
    | | main.cpp
    | |
    ---tests
    | tests.pro (G)
    \ testinputvectors.cpp (H)
    @

    File A (buildInfo.pri):
    @
    ROOT_DIRECTORY = $$PWD
    BUILD_DIRECTORY = $${ROOT_DIRECTORY}/build
    TESTS_DIRECTORY = $${BUILD_DIRECTORY}/tests
    @

    File B (libraryIncludes.pri):
    @
    INCLUDEPATH += $$PWD/MyApp
    DEPENDPATH += $$PWD/MyApp
    @

    File C (MyApp.pro):
    @
    include(buildInfo.pri)

    This variable contains the name of the template to use when generating the project.

    "subdirs"-option: Creates a Makefile for building targets in subdirectories.

    The subdirectories are specified using the SUBDIRS variable. For more information see:

    http:#qt-project.org/doc/qt-5/qmake-variable-reference.html#template

    TEMPLATE = subdirs

    specify directory for target file

    DESTDIR = $${BUILD_DIRECTORY}

    where to place intermediate object files

    OBJECTS_DIR = $${BUILD_DIRECTORY}

    where to place intermediate moc files

    MOC_DIR = $${BUILD_DIRECTORY}

    SUBDIRS +=
    MyApp
    tests
    @

    File D (MyApp.pro):
    @
    include(../buildInfo.pri)

    TEMPLATE = app

    QT += qml
    quick
    gui
    widgets
    core

    specify directory for target file

    DESTDIR = $${BUILD_DIRECTORY}

    where to place intermediate object files

    OBJECTS_DIR = $${BUILD_DIRECTORY}

    where to place intermediate moc files

    MOC_DIR = $${BUILD_DIRECTORY}

    SOURCES += main.cpp
    inputvectors.cpp \

    RESOURCES += qml.qrc

    Default rules for deployment.

    include(deployment.pri)

    HEADERS +=
    inputvectors.h
    @

    File E (inputvectors.h):
    @
    #ifndef INPUTVECTORS_H
    #define INPUTVECTORS_H

    #include <QList>
    #include <QString>

    class InputVectors
    {

    public:
    InputVectors();
    InputVectors(QList<QString> columnHeadings,
    QList<QList<unsigned int> > table);

    QList<QString> getHeadings();
    QList<QList<unsigned int> > getValues();
    

    private:
    QList<QString> columnHeadings;
    QList<QList<unsigned int> > table;
    };

    #endif // INPUTVECTORS_H
    @

    File F (inputvectors.cpp):
    @
    #include "inputvectors.h"

    InputVectors::InputVectors(QList<QString> columnHeadings,
    QList<QList<unsigned int> > table)
    {
    this->table = table;
    this->columnHeadings = columnHeadings;
    }

    QList<QList<unsigned int> > InputVectors::getValues()
    {
    return this->table;
    }

    QList<QString> InputVectors::getHeadings()
    {
    return this->columnHeadings;
    }
    @

    File G (tests.pro):
    @
    include(../buildInfo.pri)

    QT += testlib
    core

    CONFIG += testcase

    include(../libraryIncludes.pri)

    DESTDIR = $${TESTS_DIRECTORY}
    OBJECTS_DIR = $${TESTS_DIRECTORY}
    MOC_DIR = $${TESTS_DIRECTORY}

    SOURCES +=
    testinputvectors.cpp

    File H (testinputvectors.cpp):,
    #include <QtTest/QtTest>

    #include "inputvectors.h"

    class TestInputVectors: public QObject
    {
    Q_OBJECT

    private slots:
    void openFile();
    };

    void TestInputVectors::openFile() {
    QList<QString> columnHeadings;
    columnHeadings.append("test");
    QList<unsigned int> tmp;
    tmp.append(2);
    QList<QList<unsigned int> > table;
    table.append(tmp);
    InputVectors test = InputVectors(columnHeadings, table);
    }

    QTEST_MAIN(TestInputVectors)
    #include "testinputvectors.moc"
    @

    When I change the "TEMPLATE = app" to "TEMPLATE = lib" in the MyApp.pro (D) file and link it inside the libraryIncludes.pri, it all works as expected. However, when I write the "TEMPLATE = app", I get an error message:

    bq. testinputvectors.cpp:20: undefined reference to `InputVectors::InputVectors(QList<QString>, QList<QList<unsigned int> >)'
    collect2.exe: error: ld returned 1 exit status

    BTW: QtCreate does not mark the #include "inputvectors.h" with a wavy underline as it would normally do if it cannot find a file.

    How can I access the functions to be tested from the testing-project?

    Thanks in advance,
    mozzbozz

    TL;DR: I have two subprojects (main and tests) on the same layer where I want to test the main "MyApp"-project with the tests placed inside the "tests"-project. However, MyApp is not "TEMPLATE = lib" but "TEMPLATE = app" and I cannot figure out how to correctly access the functions of MyApp from tests.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You can't link against an application.

    You have two options there:

    Put the core code and tests in a library and use it to build your application

    Build the sources you want to test against within test project.

    Hope it helps



  • Hmm, that's not the answer I wanted to hear... at least I know now, why I could not get this working.

    I think I will place the tests folder inside the main project then, without having a common parent project... Because there is no way to put _everything _ inside a seperate lib.

    Thanks!


  • Lifetime Qt Champion

    Then use the second technique, build the class for your test along the test



  • Ok, I'm still struggling with this problem. I now have the following:

    @
    MyApp
    |---MyApp.pro
    |---myclass.h
    |---myclass.cpp
    |---main.cpp
    |---tests
    ---testmyclass.cpp
    @

    Inside the testmyclass.cpp-file I have the obligatory
    @
    QTEST_MAIN(TestFileHandler)
    @

    --> of course I keep getting the

    bq. multiple definition of `qMain(int, char**)'

    error... I have to admit that I'm a bit puzzled now: How could I organize the testing now? :/

    mozzbozz

    (unsolved the topic again)


  • Lifetime Qt Champion

    Keep the tests outside the app folder

    e.g.

    MyProject
    --- MyApp
    --- MyLib(s)
    --- MyTests



  • Ok, just found "this":http://stackoverflow.com/questions/9780602/using-qt-unit-tests-in-a-project-conflicting-main-functions which says about the same. If I can make this work, I'm gonna resolve this topic again.

    Thanks for your help!



  • Thank you SGaist!

    Well, I've finally managed to get it up working. The magic was setting the "VPATH variable":http://qt-project.org/doc/qt-5/qmake-variable-reference.html#vpath in qMake.

    Just for reference, this is what I have now (in case someone else has the same problems):
    @
    MyProject
    |--MyApp
    | |---MyApp.pro
    | |---myclass.h
    | |---myclass.cpp
    | ---main.cpp
    |
    |--tests
    |---tests.pro
    |---testmyclass.cpp
    ---main.cpp
    @

    My tests.pro:
    @
    include(../buildInfo.pri)

    QT += core
    testlib

    specify directory for target file

    DESTDIR = $${BUILD_DIRECTORY}_tests

    where to place intermediate object files

    OBJECTS_DIR = $${BUILD_DIRECTORY}_tests

    where to place intermediate moc files

    MOC_DIR = $${BUILD_DIRECTORY}_tests

    make compiler aware of the application-to-be-tested-directory

    (needed for the #include-statements in the sourcecode)

    INCLUDEPATH += $${APP_DIRECTORY}

    make qmake aware of the application-to-be-tested-directory (so it

    will find the files specified in SOURCES and HEADERS)

    VPATH += $${PWD}
    $${APP_DIRECTORY}

    SOURCES += main.cpp
    myclass.cpp
    testmyclass.cpp

    HEADERS +=
    myclass.h
    testmyclass.h
    @

    My buildInfo.pri:
    @
    ROOT_DIRECTORY = $$PWD
    APP_DIRECTORY = $$PWD/MyApp
    BUILD_DIRECTORY = $${ROOT_DIRECTORY}/build
    @

    My testmyclass.h:
    @
    #ifndef TESTFILEHANDLER_H
    #define TESTFILEHANDLER_H

    #include <QObject>

    class TestMyClass: public QObject
    {
    Q_OBJECT

    private slots:
    void myTest();
    };

    #endif // TESTFILEHANDLER_H
    @

    My testmyclass.cpp:
    @
    #include <QtTest/QtTest>
    #include "myclass.h"

    void TestFileHandler::myTest() {
    MyClass c;
    QCOMPARE(c.printHello(), "Hello");
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.