Skip to content

Testing your code

Friday, 23 July 2004  |  zack rusin

This is another blog entry from the series of "how to improve my code". I was very happy with the response I got to the "delayed initialization" entry. Today I'll show you how to prove your code is working or at least doing what's expected. I'll talk a little bit about unit testing. If you hate "extreme programming" or "test driven development" bare with me as I'll show you how to very quickly and easily write tests.
There's quite a few frameworks that were designed to ease testing. If you're into testing you probably have your favorite one. If you're researching those framework there are two things which you should look at foremost:

  1. How easy it is to add new tests. This one is very important because in reality no one wants to write tests and if it takes a lot of code no one will. So the less code to write the better.
  2. How flexible is the testing functionality there. Many frameworks allow you to compare only strings. You don't want that, you want to be comparing many different types, dependingly on the test.


Personally I didn't find a framework that would nicely integrate with KDE and C++ so I wrote my own. Enter KUnitTest. For now I licensed it under BSD license but I might consider putting it under public domain since it looks like we'll be using it in some commercial products.
KUnitTest is a very, very small library consisting of the following parts:
  • kunittest.{h,cpp} - it's the test factory, holds all tests and runs them,
  • tester.h - which holds the base of a pure test object. "Pure test object" in the KUnitTest is one that doesn't require Qt event loop to run.
  • qtester.{h,cpp} - which holds the base of a test object which requires Qt event loop to perform its tests.

Now lets see how you would add a new test to KUnitTest. You do that by writting a Tester derived class which has the "allTests()" method. Like so: class SampleTest : public Tester { public: SampleTest();

public: void allTests(); };
Now in the allTests method we implement our tests. Which for example look as follows: void SampleTest::allTests() { CHECK( 3+3, 6 ); CHECK( QString( "hello%1" ).arg( " world not" ), QString( "hello world" ) ); } the check method is template based so as long as the variables which you pass to it have an equals ('==' ) operator you will get a type safe comparison.
Now that you did that the only other thing to do is in the kunittest.cpp add ADD_TEST( SampleTest ); call in the "void registerTests()" method.
You're done. KUnitTest will do the rest. It will tell you which tests failed, how, what was the expected result, what was the result it got, what was the code that failed and so on. For example for the code above it would output:

tests: SampleTest errors:
tests:  sampletest.cpp[38]: failed on "QString( "hello%1" ).arg( " world not" )"
tests:           result = 'hello world not', expected = 'hello world'

Finally, how to integrate kunittest with your app/lib? What you do is copy the following files: main.cpp, tester.h, kunittest.h, kunittest.cpp, qtester.h, qtester.cpp and Makefile.am to your test directory. Then you start writting tests and run 'make check' to see what changed. Have fun.
If you have ideas on how to make it even more simpler let me know! (I will not respond to anyone who will want testing units to not be classes though :) )