Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Correct project structure for QTest with qbs.



  • Hi Guys,
    I'm trying to write a Unit Test for a production code class MyCustomClass . I'm using qbs as build System, Qt 5.8.0 and QtCreator. My production code and my QTest are separate Applications which are bundled together into one Project. The test case runs well if I put a simple QFAIL in it, but as soon as I try to use (create an object) of MyCustomClass the Linker complains about an undefined reference to MyCustomClass members.

    C:\Users\SS76986\Documents\AutotestEval\tests\testcase1\tst_testcase1.cpp:32: error: undefined reference to `MyCustomClass::MyCustomClass()'
    C:\Users\SS76986\Documents\AutotestEval\tests\testcase1\tst_testcase1.cpp:33: error: undefined reference to `MyCustomClass::add(int, int)'
    

    Can anyone tell me how to get rid of the complains? I'm not even sure if the Project structure I chose is correct.
    Since I'm not able to upload the whole Project as zip File I'll Show you the files which are relevant.
    Project Structure:
    0_1550243605513_projectStructure.JPG
    ProjectFile (AutotestEval.qbs):

    import qbs
    
    Project {
        name: "AutotestEval"
        references: [
    	"src/",
            "tests/"
        ]
    }
    

    Production Code Product (src.qbs):

    import qbs
    
    QtApplication {
        name: "TheApp"
    
        Export {
                Depends { name: "cpp" }
                cpp.includePaths: product.sourceDirectory
                cpp.defines: ["MYSHAREDLIB_LIBRARY"]
        }
    
    
        Group{
            name: "Grp_Main"
            files: [
                 "main.cpp",
                 "mycustomclass.cpp",
                 "mycustomclass.h",
            ]
        }
    }
    

    Unit Test Product (test.qbs):

    import qbs
    
    CppApplication {
        name: "Testcase1"
    
        Depends { name: "Qt.testlib" }
        Depends { name: "TheApp" }
    
    
        Group{
            name: "Testcase1"
            files: ["tst_testcase1.cpp"]
        }
    }
    

    Test Sourcecode (tst_testcase1.cpp)

    #include <QtTest>
    #include <mycustomclass.h>
    
    // add necessary includes here
    
    class testCase1 : public QObject
    {
        Q_OBJECT
    
    public:
    
    private slots:
        void test_case1();
    
    };
    
    void testCase1::test_case1()
    {
        // This does not work!
            MyCustomClass sut;
            QVERIFY(sut.add(1,1) == 2);
    
        // This works well
        //QFAIL("Hello Fail!");
    }
    
    QTEST_APPLESS_MAIN(testCase1)
    
    #include "tst_testcase1.moc"
    
    


  • I found a solution for the issue: Simply split the main() from the rest of the Project . Here is the updated Production Code Product specification:

    import qbs
    
    Project {
        name: "TheRealApp"
    
        QtApplication {
            name: "TheApp"
    
            Depends { name: "cpp" }
            Depends { name: "library" }
    
            Group {
                name: "Main"
                files: [
                    "main.cpp",
                ]
            }
    
        }
    
        StaticLibrary{
            name: "library"
    
            Depends { name: "cpp"     }
            Depends { name: "Qt.core" }
            Export {
                Depends { name: "cpp" }
                cpp.includePaths: product.sourceDirectory
            }
    
            Group{
                name: "Grp_Main"
                files: [
                    "mycustomclass.cpp",
                    "mycustomclass.h",
                ]
            }
        }
    }