Some features include:
- Creates a stub tests for each non private function in the class.
- Creates a subclass for the class to expose any protected functions for testing.
- Creates a basic sanity test that just calls each function.
- Creates a _data() function for each test.
- Populates the _data() functions with columns for each argument and the return value.
- Adds QFETCH stub code that matches the generated _data function as a place to start from.
- Adds the four init and cleanup functions with documentation so you don't have to look up what does what.
- Adds signal spys to each tests if the class contains any signals.
The source code can be found: QAutoTestGenerator
Here is an example class:
class Example : QObject
{
Q_OBJECT
signals:
void done();
public:
void launch(int value);
protected:
bool crashed();
};
And the generated stub:
#include <QtTest/QtTest>
#include <example.h>
class tst_Example : public QObject
{
Q_OBJECT
public slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
private slots:
void example_data();
void example();
void launch_data();
void launch();
void crashed_data();
void crashed();
void done_data();
void done();
};
// Subclass that exposes the protected functions.
class SubExample : public Example
{
public:
bool call_crashed()
{ return SubExample::crashed(); }
void call_done()
{ return SubExample::done(); }
};
// This will be called before the first test function is executed.
// It is only called once.
void tst_Example::initTestCase()
{
}
// This will be called after the last test function is executed.
// It is only called once.
void tst_Example::cleanupTestCase()
{
}
// This will be called before each test function is executed.
void tst_Example::init()
{
}
// This will be called after every test function.
void tst_Example::cleanup()
{
}
void tst_Example::example_data()
{
}
void tst_Example::example()
{
SubExample example;
/*
example.isDone();
example.launch();
example.call_crashed();
example.call_done();
*/
QVERIFY(false); // remove after test is implemented
}
void tst_Example::launch_data()
{
QTest::addColumn<int>("value");
QTest::newRow("null") << 0;
}
// public void launch(int value)
void tst_Example::launch()
{
/*
QFETCH(int, value);
SubExample example;
QSignalSpy spy0(&example, SIGNAL(done()));
QCOMPARE(spy0.count(), 0);
example.launch();
*/
QVERIFY(false); // remove after test is implemented
}
void tst_Example::crashed_data()
{
/*
QTest::addColumn<bool>("crashed");
QTest::newRow("null") << 0;
*/
}
// protected bool crashed()
void tst_Example::crashed()
{
/*
QFETCH(bool, crashed);
SubExample example;
QSignalSpy spy0(&example, SIGNAL(done()));
QCOMPARE(spy0.count(), 0);
example.call_crashed();
*/
QVERIFY(false); // remove after test is implemented
}
void tst_Example::done_data()
{
QTest::addColumn<int>("foo");
QTest::newRow("null") << 0;
}
// protected void done()
void tst_Example::done()
{
/*
QFETCH(int, foo);
SubExample example;
QSignalSpy spy0(&example, SIGNAL(done()));
QCOMPARE(spy0.count(), 0);
example.call_done();
*/
QVERIFY(false); // remove after test is implemented
}
QTEST_MAIN(tst_Example)
#include "tst_example.moc"

6 comments:
That's way cool.
This takes unit testing with Qt from "really easy" to "I love doing this".
One minor gripe would be the missing 'e' in the generated tst classes. :)
Overall fantastic work. Thanks for sharing it.
The "tst" is historical I guess you could say. All of the tests for Qt use it so I just copied it.
This looks like a pretty handy tool, for sure. Now if only I could find an easy way to build and run a whole bunch of QTest unit tests in a single directory...
@ilkka: Why can't you just write a makefile to build all of the tests and run them in a directory?
@benjamin: because that's what qmake is for :) But as it happens, just today I discovered that if one creates a qmake .pro file with TEMPLATE=subdirs, one can then set SUBDIRS to a list of .pro files in the same directory... this method combined with clever includes lets me easily do what I want, and qmake does all the heavy lifting for me.
...reading my comment again I see that I should start a software engineering blog myself, for topics that perhaps demand a bit more verbosity than a mere couple of sentences :)
Post a Comment