I started writing some tests with Qt's unit testing system.
How do you usually organize the tests? It is one test class per one module class, or do you test the whole module with a single test class? Qt docs suggest to follow the former strategy.
I want to write tests for a module. The module provides only one class that is going to be used by the module user, but there is a lot of logic abstracted in other classes, which I would also like to test, besides testing the public class.
The problem is that Qt's proposed way to run tests involved the QTEST_MAIN
macro:
QTEST_MAIN(TestClass)
#include "test_class.moc"
and eventually one test program is capable of testing just one test class. And it kinda sucks to create test projects for every single class in the module.
Of course, one could take a look at the QTEST_MAIN
macro, rewrite it, and run other test classes. But is there something, that works out of the box?
So far I do it by hand:
#include "one.h"
#include "two.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
TestOne one;
QTest::qExec(&one, argc, argv);
TestOne two;
QTest::qExec(&two, argc, argv);
}
In the Test framework field, select Qt Test or Qt Quick Test. For a Qt test, select the GUI Application check box to create a Qt application. In the Test case name field, enter a name for the test case. For a Qt test, select the Requires QApplication check box to add the include statement for QApplication to the main.
Writing a Test#include <QTest> class TestQString: public QObject { Q_OBJECT private slots: void toUpper(); }; Note: You need to include the QTest header and declare the test functions as private slots so the test framework finds and executes it. The QVERIFY() macro evaluates the expression passed as its argument.
In computer programming, unit testing is a software testing method by which individual units of source code—sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures—are tested to determine whether they are fit for use.
Related to the answer posted by @cjhuitt
This is an example that removes the need of manually calling each test object
I TRY TO AVOID THINGS LIKE THIS:
MyTestClass1 t1; t1.run();
MyTestClass2 t2; t2.run();
//etc...
My solution is to let the test objects inherit from a base class that adds itself to a static list The main program then executes all the test objects in that list. In that way, none of the supporting framework code needs to be changed. The only things that change are the test classes themselves.
Here is how i do it:
qtestsuite.h - base class for the test objects
#ifndef QTESTSUITE_H
#define QTESTSUITE_H
#include <QObject>
#include <vector>
class QTestSuite : public QObject
{
Q_OBJECT
public:
static std::vector<QObject*> m_suites;
public:
explicit QTestSuite();
};
#endif // QTESTSUITE_H
qtestsuite.cpp
#include "qtestsuite.h"
#include <iostream>
std::vector<QObject*> QTestSuite::m_suites;
QTestSuite::QTestSuite() : QObject()
{
m_suites.push_back(this);
}
testall.cpp - runs the tests
#include "qtestsuite.h"
#include <QtTest/QtTest>
#include <iostream>
int main(int, char**)
{
int failedSuitesCount = 0;
std::vector<QObject*>::iterator iSuite;
for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); iSuite++)
{
int result = QTest::qExec(*iSuite);
if (result != 0)
{
failedSuitesCount++;
}
}
return failedSuitesCount;
}
mytestsuite1.cpp - an example test object, create more of these
#include "qtestsuite.h"
#include <QtTest/QtTest>
class MyTestSuite1: public QTestSuite
{
Q_OBJECT
private slots:
void aTestFunction();
void anotherTestFunction();
};
void MyTestSuite1::aTestFunction()
{
QString str = "Hello";
QVERIFY(str.toUpper() == "this will fail");
}
void MyTestSuite1::anotherTestFunction()
{
QString str = "Goodbye";
QVERIFY(str.toUpper() == "GOODBYE");
}
static MyTestSuite1 instance; //This is where this particular test is instantiated, and thus added to the static list of test suites
#include "mytestsuite1.moc"
also, to create the .pro file
qmake -project "CONFIG += qtestlib"
In our setup with QTest, we did a few things to make it nicer.
QTest::qExec()
. (We accumulate the values returned each time, and return that from our function.) main()
calls this function, and returns the result as the success/failure. This setup means that the class will be instantiated before main()
is run, so it will be added to the list of classes to test when main runs. The framework requires that you just need to inherit your class properly, and instantiate a static instance if you always want it run.
We also occasionally create other optional tests, that are added based on command line switches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With