tags:

views:

634

answers:

12

Hi

I don't know how you guys test your code every time you code a little and for different levels of testing: unit testing, Integration testing, ...

For example, for unit testing a function you just wrote, do you write another whole set of main function and Makefile to test it? Or do you modify the main function of your project to test the function. Or do you just run your project under debugging, and stop at where the function is about to be called and modify the values of its arguments?

I believe there must be some convenient and common ways that most people are using and only I am not aware of.

Thanks and regards!

+1  A: 

Have you looked at http://CppUnit.sourceforge.net ?

Ruben Bartelink
I like cppunit as a lightweight unit test framework. :-)
Paul Nathan
+2  A: 

I use googletest/gtest

ctacke
+2  A: 

I usually do this way:

int foo(int bar) {
   ...
}

#ifdef FOO_UNITTEST
int main(int argc, char *argv[]) {
    // tests
}
#endif

And I have a makefile which has -DFOO_UNITTEST in CFLAGS.

It's clumsy but you always have your tests just beside your code.

qrdl
+1 Good demonstration of a basic unit test.
Shiftbit
+1  A: 

You should also consider running a test coverage tool to see if your tests actually exercise enough of the code to be a good set of tests. See SD Test Coverage for C.

Ira Baxter
A: 

I generally start out with something about as complicated as MinUnit then build up a set of macros which suits the project I'm working on to suit that project's conventions.

Each component will have an executable which builds and runs the unit tests for that component.

I don't use a debugger as that requires human intervention, so you can't use it for automatic regression. I don't modify the main executable, as that usually involves many components and is quite complicated enough without having lots of macros to switch bits on and off. Creating a new target using make is very easy.

Pete Kirkham
+3  A: 

xUnit is a family of unit testing modules. x is replaced by a letter for the language of framework used. The family currently consists of:

I've worked in projects using CppUnit with good results. Recently I've tried to integrate this in an automatic build environment (i.e. Hudson) and I came across many obstacles.

Ideally, the build automatically builds and runs the unit tests. In that case, code is run from the test environment (and thus has it's own main loop). An extra complication in my case is that I work with embedded systems; printf is not always possible. I expect that if you run on PC, CUnit and CppUnit can help you a lot to implement good unit testing. Please look at how to use the results; a continuous integration system will increase your effiency a lot.

Another framework worth to give a look is Maestra. It relies on C99 (which Microsoft has never implemented, but for gcc it is great!)

Adriaan
+6  A: 

The approach of Test Driven Development (TDD) is to first write the test, see that it fails by default (i.e., a new test succeeds by failing), then write the function to pass the test.

In this way, testing becomes not an afterthought, but the very core of your development methodology.

Because you may be developing a function (method) before you have implemented the objects upon which it operates, most TDD frameworks also provide a facility for generating "mock" objects, which will return expected results before their classes are actually implemented.

I personally recommend Google Test and Google Mock:

http://code.google.com/p/googletest/

http://code.google.com/p/googlemock/

Buggieboy
A: 

I love UnitTest++. It's really easy to set up, and writing tests is easier than with the typical favourite, CppUnit. Each test has very little coding overhead so you're more likely to write them!

As for what I test, I tend to test the public interfaces of classes, but if I'm just doing some refactoring and splitting things up into smaller functions I won't write a set of tests for each of those functions - they should be covered by the tests testing the public interface. As long as the public interface works according to the tests, all is well in the world.

Ben Hymers
+2  A: 

I've learnt to love googletest/googlemock. They are a very powerful combination and easy to use. There is also a lot of documentation available on their wiki pages.

googletest: code.google.com/p/googletest/wiki/GoogleTestPrimer

googlemock: code.google.com/p/googlemock/wiki/ForDummies

ingorichter
+1  A: 

I love googletest and googlemock. Really easy to configure and well documented, here there is a good introduction to the framework.

Enric Ruiz
+1  A: 

I use boost.test. I moved to it from cppunit, which was good but too java like, this was a problem because junit uses reflection to find and run your tests, since this is not available in c++ you have to use macros to register your tests, in cppunit you have to declare, register and define your tests in three different places. boost.test lets you declare, register and define your test in one statement this is very nice.

My general approach is to TDD new code and try to use unit test judiciously for legacy code. I esp test any code that is different on different platforms to ensure they behave the same and continue to behave the same.

I structure my projects so that every library or executable project also has a unit test project. For executable tests, I include the executable source files (except main) in the test project and add my test in new files. For library tests, I normally just link to the library except when I am testing private parts of dlls then I use the executable approach.

Using CMake enables you to abstract any duplication between source project and test project. Also CTest integrates well with any unit testing framework that package tests in executables. This lets you run all test executables in a solution in one go and reports a summary of the results. It also integrates with a continuous integration framework called CDash.

A note on TDD, a lot of people treat this as Test driven development but it can be Test Driven Design. This is a very good way to focus on agile design, using TDD for designing my software as well as writing it really opened my eyes.

iain
+2  A: 

Comparing CppTest and CppUnit I would go with CppTest. CppTest has less hidden framework and IMO easier to understand and implement. I personally like to see the main entry point. I have also included Boost Unit Testing Framework. It is not xUnit based. I am not a fan, but if you are already using the Boost Library it would be nice to incorporate.


CppTest vs CppUnit

Ease of creating a unit test and test suite. Both CppUnit and CppTest create unit tests of class methods, with the class itself derived from some tool-provided Test class. The syntax for CppTest is slightly simpler, though, with the test registration happening inside the class constructor. In the case of CppUnit, the additional macros CPPUNIT_TEST_SUITE and CPPUNIT_TEST_SUITE_ENDS are needed.

Running the tests. CppTest simply calls the run method on the test suite, while CppUnit uses a separate TestRunner class whose run method is invoked for running the tests.

Extending the testing hierarchy. In the case of CppTest, it is always possible to extend the previous test suite by creating a new class that inherits from the old one. The new class will define some additional functions that add to the unit test pool. You simply invoke the run method on the object of the new class type. CppUnit, in contrast, requires that you use the macro CPPUNIT_TEST_SUB_SUITE along with class inheritance to achieve the same effect.

Generating formatted output. Both CppTest and CppUnit have the ability to customize the output. However, although CppTest has a useful, predefined HTML output formatter, CppUnit does not. However, CppUnit exclusively supports XML formatting. Both support text and compiler style formats.

Creating test fixtures. To use test fixtures, CppUnit requires that the test class be derived from CppUnit::TestFixture. You must provide definitions for the setup and tear-down routines. In the case of CppTest, you need to provide definitions only for the setup and tear-down routines. This is definitely a better solution, as it keeps the client code simple. •Predefined utility macro support. Both CppTest and CppUnit have a comparable set of macros for asserts, handling floats, and so on.

Header files. CppTest requires that you include a single header file, while CppUnit client code must include multiple headers, like HelperMacros.h and TextTestRunner.h, depending on the features used.

http://www.ibm.com/developerworks/aix/library/au-ctools3_ccptest/index.html?ca=drs-


CPPTEST

#include “cppTest.h”

class myTestWithFixtures : public Test::Suite { 
  void function1_to_test_some_code( );
  void function2_to_test_some_code( );

  public: 
  myTestWithFixtures ( ) { 
      TEST_ADD (function1_to_test_some_code) {...}; 
      TEST_ADD (function2_to_test_some_code) {...}; 
  } 

  protected: 
    virtual void setup( ) { ... };
    virtual void tear_down( ) { ... };
}; 

int main ( ) 
{ 
  myTestWithFixtures tests; 
  Test::TextOutput output(Test::TextOutput::Verbose);
  return tests.run(output);
} 

http://www.ibm.com/developerworks/aix/library/au-ctools3_ccptest/index.html?ca=drs-


CPPUNIT

#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TextTestRunner.h>
#include <cppunit/extensions/HelperMacros.h>

class mystringTest : public CppUnit::TestFixture {
public:
  void setUp() { ... };
  void tearDown() { ... };

  void function1_to_test_some_code() { ... };
  void function2_to_test_some_code() { ... };

  CPPUNIT_TEST_SUITE( mystringTest );
  CPPUNIT_TEST( function1_to_test_some_code );
  CPPUNIT_TEST( function2_to_test_some_code );
  CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION( mystringTest );

with out macros

int main ()
{
  CppUnit::TestSuite* suite = new CppUnit::TestSuite("mystringTest");
  suite->addTest(new CppUnit::TestCaller<mystringTest>("checkLength",
                &mystringTest::checkLength));
  suite->addTest(new CppUnit::TestCaller<mystringTest>("checkValue",
                &mystringTest::checkLength));

  // client code follows next 
  CppUnit::TextTestRunner runner;
  runner.addTest(suite);

  runner.run();
  return 0;
}

http://www.ibm.com/developerworks/aix/library/au-ctools2_cppunit/


Boost Unit Testing Framework

#include <boost/test/unit_test.hpp>

using namespace std;

struct CMyFooTestFixture
{
    CMyFooTestFixture() { ... } //SetUp
    ~CMyFooTestFixture() { ... } //TearDown

    void function1_to_test_some_code(CMyFoo& foo) { ... };
    void function2_to_test_some_code(CMyFoo& foo) { ... };
}

BOOST_FIXTURE_TEST_SUITE(MyFooTest, CMyFooTestFixture);

BOOST_AUTO_TEST_CASE(function1_to_test_some_code)
{
    CMyFoo foo;
    function1_to_test_some_code(foo);
}

BOOST_AUTO_TEST_CASE(function1_to_test_some_code2)
{
    CMyFoo foo;
    function1_to_test_some_code(foo);
}

BOOST_AUTO_TEST_SUITE_END();

http://www.beroux.com/english/articles/boost_unit_testing/

Shiftbit