Many people are looking for information about which particular C++ unit testing framework they should use for their project and there are also many articles discuss the topic but few articles talk about mock frameworks which are even more important factor when applying unit testing in practice and they have much greater effect on the productivity when doing test-driven development.

Test-driven development in a nutshell

My first experience with unit testing happened to be during my university studies. As we learned Java development, we also worked a little with JUnit as it is the most popular unit testing framework for Java and also the grandfather of almost all current frameworks. I felt about it like pain in the a** because it seemed ridiculous to use it for our very dummy programs and because I’m really not a big fan of Java and it’s monolithic development environment called NetBeans, but I will talk about it in another article.

Next I’ve met unit testing at my current job where we used TNSDLUnit which is a proprietary framework developed by the employees as an internal open-source project for our TNSDL language. Basically this framework is just a TNSDL specific version of the well known CPPUTest framework. This time I’ve seen real life examples and I soon discovered the potentials in unit testing and in particular its application in test-driven development.

Test-driven development, or TDD in short, is a software development process that became very popular in the recent past and not accidentally as it is a very powerful tool in good hands. It introduces a very simple development cycle that results in simple, clean and test covered code. The process consists of five straightforward steps:

  1. Add a test – this is made based on a particular requirement
  2. Run all tests and see if the new one fails – this ensures that the test really needs modification to the code
  3. Write some code – modify code to make the new test pass
  4. Run all tests and see them succeed – if the implementation is good then the new test now must pass
  5. Refactor code – tidy up the code as you can be sure now that if you do something wrong then tests will fail

Not just this development method provides 100% test coverage for your code but it forces you to make the implementation based on requirements not vice versa.

TDD in a more strict manner also states that one must not write more code than it is necessary to make the test pass. This results sometimes in very awkward implementation stubs at the beginning but it prevents the developer from creating untested code (note that 100% coverage usually does not enough for proper testing).

Why use unit testing?

Many people have concerns about the necessity of testing and ask why test and why use unit testing. Well, as it maybe seems ridiculous to unit test a code which consists of a few hundreds or thousands of source line and is perspicuous even for the less competent people, the importance of testing comes into force when developing huge sized codes which are continuously modified by a group of people. One can not just test whether a newly implemented functionality is working as expected but can execute automated regression sets in order to ensure that no old functionality is crashed due to a modification.

Others have concerns about that unit testing doubles the code as so increases maintenance because the testing code is as big as the implementation itself. By the way, in a real life example the testing code can even be double the size of the production code. However, the added benefit of a well tested product eliminates most of the cost of bug fixes as they are discovered in the very beginning of the development process.

C++ unit test frameworks

When I’ve started to work with C++ one of my first thing was to look around for a good unit test framework. There are plenty of them so I will mention only some of the most popular ones: CPPUnit, CPPUTest, CxxTest, UnitTest++, Boost Test Library, GoogleTest, etc.

Most people spend too much time on deciding which unit test framework to use while they all have very similar syntax structure and all support the most needed assertions and facilities that are needed to get started with TDD. I think this is just a matter of taste.

Resolving dependencies

As one starts to actively use unit testing will face difficulties that rise from the dependencies between different elements of the software system, whether it be an external database, a foreign module or just an own class referenced by the code unit under test. These problems force people to write stubs or mocks to remove external dependencies.

Stubs are just not flexible enough and writing mocks sometimes seems to be too expensive. However, both have a great penalty on development time and maintenance cost. So, at a point, dependencies become the main problem and as such the relevance of which unit test framework to use gets hidden and people start to look for a mock framework. These libraries not just enable easy creation of mock objects but also integrates them tightly into the unit test framework and sometimes they even provide automated mock generation. Fortunately there are also plenty of mock frameworks for C++. Here are some of them: mockpp, Mock Objects, mockcpp, GoogleMock, etc.

Here the differences are much more visible from both from usability, portability and maturity point of view. Some of them automatically generate mocks, others need code for that as well. Some of them depend on specific application binary interface (ABI) formats, others not. Some of them need exotic language features while others work on all the significant compilers. Also, due to the complexity of the C++ language it is very hard to correctly parse code that is heavily obfuscated by macros, so in many cases the automatic generation of mocks simply doesn’t work.

I’ve put my vote on GoogleMock and as such I started to use GoogleTest as a unit test framework because of the following reasons:

  • It does not depend on any special language feature or ABI format so it’s portable
  • It is natively integrates with GoogleTest so no need to worry about compatibility issues
  • Mocks have to be hand written, however it needs just a few lines of code (it also has a mock generator, however I don’t use it)

Summary

As a final conclusion, if you take my advice then you don’t take anybody’s advice. Try it out yourself and see it whether a particular tool set fits your taste or not. It strongly depends on what you plan to unit test. Just keep it simple and have fun with TDD. Yes, it’s really fun!