QUnit is not really meant to replace anything. If your development environment already supports a unit test framework, you should probably just use that framework. But sometimes there is no framework waiting for you, and then, perhaps, QUnit is what you need.
There is really just one file you need to care about:
Stuff it into the directory you want to write your unit tests, and off you go.But you may also download the whole package to with some examples of usage and more:
or you may check out from Subversionsvn co https://qunit.svn.sourceforge.net/svnroot/qunit qunitIf you have ideas on how to improve QUnit please contact me (oma|at|pvv.org).
Suppose you are about to make a small program. First you create a new directory, and then you need a unit test framework. If it is just a one-shot exercise then perhaps you just want to download QUnit.hpp into your new directory.
Now, suppose you want to design and implement class Foo
. First
you create an empty class Foo
, eg Foo.hpp
might
look like:
// Foo.hpp class Foo { };Then, you write a unit test for this class.
FooTest.cpp
might look like this:
// FooTest.cpp #include "Foo.hpp" #include "QUnit.hpp" #include <iostream> int main() { QUnit::UnitTest qunit(std::cerr, QUnit::normal); Foo f; QUNIT_IS_EQUAL(42, f.theAnswer()); return qunit.errors(); }And you can now compile and run your unit test:
g++ FooTest.cpp && ./a.out(Notice how we execute the unit test only if the code compile and link correctly. This is a key feature of QUnit, as you will see later.)
First the compilation will fail, and might print out something like:
FooTest.cpp: In function 'int main()': FooTest.cpp:10: error: 'class Foo' has no member named 'theAnswer'You fix it by adding the proper method to Foo. Eg,
// Foo.hpp class Foo { public: int theAnswer() { return 0; } };Now it will compile and link, but this time the unit test will fail and it might print out something like:
FooTest.cpp:10: FAILED/main(): compare {42} == {f.theAnswer()} got {"42"} == {"0"}As you see, you now get an error message because the unit test is failing. Notice that the format of the error message is such that most development environments will recognize it as a regular error message and will help you to find the file and line of the error. This is useful.
You fix the code again:
// Foo.hpp class Foo { public: int theAnswer() { return 42; }; };and now your code compiles, links and the unit tests run without complaining. You are ready to add another test.
Here is a slightly more advanced example:
// QUnitDemo.cpp // // an example of how to use QUnit (qunit.sourceforge.net) // // g++ QUnitDemo.cpp && ./a.out // #include "QUnit.hpp" #includeThat's basically it...class QUnitDemo { QUnit::UnitTest qunit; int theAnswer() { return 42; } void test1() { QUNIT_IS_EQUAL(42, theAnswer()); QUNIT_IS_EQUAL("42", theAnswer()); QUNIT_IS_TRUE(theAnswer() == 42); QUNIT_IS_FALSE(43 == theAnswer()); } void test2() { QUNIT_IS_NOT_EQUAL(43, theAnswer()); std::string str = "The Answer Is 42"; QUNIT_IS_EQUAL("The Answer Is 42", str); QUNIT_IS_FALSE(std::string::npos == str.find("The Answer")); } public: QUnitDemo(std::ostream & out, int verboseLevel = QUnit::verbose) : qunit(out, verboseLevel) {} int run() { test1(); test2(); return qunit.errors(); } }; int main() { return QUnitDemo(std::cerr).run(); }
No wait. What about test suites? Ah, no problem. Just make a target in your Makefile depending on a number of test cases. Eg,
MyTestSuite: FooTest BarTest GazTest @echo "Test Suite OK"or you can make a TestSuite.cpp like this:
// ... int main() { int errors = 0; errors += FooTest(std::cerr).run(); errors += BarTest(std::cerr).run(); errors += GazTest(std::cerr).run(); return errors; }