QUnit Home | Browse Source | Download | Discussion Forum | Project Summary

QUnit - A very small unit test framework for C++

QUnit is yet another unit testing framework for C++. However, unlike other frameworks, QUnit feels like 50 lines of code, integrates nicely into your development environment, and contains no bells and whistles. QUnit is more like an idiom - once you have used it a couple of times you might start implementing it whenever you need it, in the language and environment that you are currently working with.

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 Subversion
svn co https://qunit.svn.sourceforge.net/svnroot/qunit qunit
If you have ideas on how to improve QUnit please contact me (oma|at|pvv.org).

Tutorial

Here is a quick tutorial about how you might want to use QUnit. I assume you know about Test-driven development already.

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"

#include 

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();
}
That's basically it...

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;
}

Useful Links