[Solved] QTest issue creating object to test with
-
Hi Folks,
I'm trying to wrap my head around unit tests. I have a small class used to create an SQLite interface, which will eventually be utilised by the rest of the application, for which I would like to write some unit tests. I have manually checked that the functions perform as required, so its a simple case of automatically verifying what I have already done.
However, when I attempt to instantiate the backend as an object in my test class, I end up with a bunch of function undefined errors. What is strange is that the same method of instantiating the backend works fine in the full application...
The backend class inherits from QSqlRelationalTableModel, for the code below I am using the data setup in the Books SQL demo.
For reference, this is how I instantiate the class in the primary application, which works:
int main(int argc, char *argv[]) { //set Library Paths QCoreApplication::addLibraryPath ("libs/"); QApplication app(argc, argv); QQmlApplicationEngine engine; QApplication::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()) ); SQLite_Backend *mData = new SQLite_Backend; mData->setDatabase("/path/to/my/SQLite/database/file"); //Setup the database query for the model QString data_query; data_query = "select books.id, books.title, authors.name as auth_name, " data_query += "genres.name as genre_name, books.year, books.rating\n"; data_query += "from books\n"; data_query += "join authors on authors.id = books.author\n"; data_query += "join genres on genres.id = books.genre"; mData->setQuery(data_query); engine.rootContext ()->setContextProperty ("Data", mData); engine.load(QUrl(QStringLiteral("qrc:/demo.qml"))); return app.exec(); }
The above code works perfectly, with data showing up in the dummy QML file I've been using to test.
In my unit tests I would like to test each custom method of the class, i.e.
- Can I add/remove records?
- Can I add/remove tables?
- Can I evaluate SQL Statements correctly
etc.
As such I am presuming that I will need to create an instance of the backend, call its functions and compare the results with what is actually in the database. For now I can do that with a hard code. i.e.
QCOMPARE(mData.getRowCount("books"), 5)
When attempting to instantiate the backend inside a test case in the exact same way as above I end up with the following errors:
SQLiteBackend_Test.cpp:31: undefined reference to `SQLite_Backend::SQLite_Backend(QObject*)' SQLiteBackend_Test.cpp:31: undefined reference to `SQLiteBackend_Test::mDbWrapper' SQLiteBackend_Test.cpp:36: undefined reference to `SQLiteBackend_Test::mDbWrapper' SQLiteBackend_Test.cpp:36: undefined reference to `SQLite_Backend::setDatabase(QString const&)' moc_SQLiteBackend_Test.cpp:84: undefined reference to `SQLiteBackend_Test::getRows()'
Could anyone point me in the direction of what I am doing wrong?
I have tried instantiating the database class in a test case (i.e. slot function), re-implementing a main, a class constructor, an initTestCase function. All of them result in the above errors.
Hopefully I'm doing something silly here, but I'm stumped!
-
At the moment I haven't included the SQLite_Backend files in the .pro, but am #include'ing the header to the library in the test class
SQLiteBackend_Test.h:
#ifndef SQLITEBACKEND_TEST #define SQLITEBACKEND_TEST #include <QApplication> #include <QTest> #include <QtSql> #include "../dataModel/SQLite_Backend.h" class SQLiteBackend_Test : public QObject { Q_OBJECT private slots: //Setup and Teardown void initTestCase(); }; #endif // SQLITEBACKEND_TEST
SQLiteBackend_Test.cpp:
#include "SQLiteBackend_Test.h" void SQLiteBackend_Test::initTestCase() { SQLite_Backend *mTarget = new SQLite_Backend; mTarget->setDatabase ("/path/to/my/SQLite/Data/file"); } //Uncomment below to run this file as a standalone test case QTEST_MAIN(SQLiteBackend_Test)
I will try including the test class in the .pro and report back, thanks for the pointer.
-
@Sam2304
The application test is basically a special application. You need to link all required source files as in a normal application. Also you need to define all Qt modules in the .pro (probable at least QT += sql in your case).class SQLiteBackend_Test : public QObject { Q_OBJECT private slots: //Setup and Teardown void initTestCase(); int getRows() const; // you did not declare and implementation is also missing ???? mDbWrapper( ... ); // you did not declare and implementation is also missing }; #endif // SQLITEBACKEND_TEST
Also you have not declared the two missing methods and their implmenentation is mssing as well.
Note: You need to check the skleletons I have added.
Furthermore, it could be better to separate the functionality of those two missing methods from your test class. -
Thank You!!!
Your advice got me to the point where a sample test actually runs!
your pointer to the missing methods prompted me to clear out all the commented gumff from the class header and source, which revealed the missing methods. I'd been staring at this for so long I hadn't seen them.
I removed those and things finally started compiling. Running make check runs the test, which is perfect!
The test itself failed, but that's simply because the test code itself is malformed.
Thank you so much for your assistance, I've been bouncing off a brick wall on this for a couple of days!
Kindest Regards,
p.s. I notice that if I comment out the includes in the test .pro file, the test still compiles and runs.. interesting!
Sam