views:

704

answers:

5

I have been using CPPUnit as a unit testing framework and am now trying to use it in an automated build and package system. However a problem holding me back is that if a crash occurs during the running of the unit tests, e.g. a null pointer dereferencing, it halts the remainder of the automation.

Is there any way for CPPUnit to recover from the exception, record the test failure and then exist gracefully rather than terminating the unit test process? Even an approach specific to null pointer dereferencing would be useful as that makes up about 90% of the issues I have had.

To be technology-specific, I am using makefiles on a Windows system.

A: 

In C/C++, the best way to recover from errors like that is to run each test in a separate process and then monitor them from a parent process. This is very easy in UNIX -- just fork() before the test begins. check supports this, and you could likely patch CPPUnit to have this behavior without much fuss.

John Millikin
Unfortunately, if you are running a very large test suite, this would be prohibitive, as there could be significant overhead introduced. Each test would take significantly more time to execute.
Jeremy Mayhew
Not in my experience; forking is very cheap, since only modified memory pages must be copied. Unless you're running hundreds of thousands of tests, the overhead of fork() is unlikely to be noticed.
John Millikin
+1  A: 

You're automating the execution of your cppunit-based unit-tests during your build process, right ?

If you were trying to use CppUnit to execute the build process, I would be tempted to say don't do that !

Could you tell us what is stopping the build process when the unit tests crash ? And what are your unit tests started by, a Makefile, a script of your own, or a continuous integration framework ?


To try to answer your question, CppUnit cannot recover from violation or segmentation errors. On Unix-like systems you should be able to catch the SIGSEGV and to continue, but in which state ?

If your crashes occur in your unit test and not in your product, then I'd recommend you to rely on assertion guards to prevent dereferencing NULL pointers:

class TestObject : public CPPUNIT_NS::TestCase
{
  CPPUNIT_TEST_SUITE(Test);
  CPPUNIT_TEST(testObjectIsReady);
  CPPUNIT_TEST_SUITE_END();

public:
  void setUp(void) {}
  void tearDown(void) {} 

protected:
  void testObjectIsReady(void)
  { 
     Object *theObject = GetObject();

     CPPUNIT_ASSERT_MESSAGE("check pointer is not null", theObject != NULL);

     //--- now you can play with your object without dereferencing a NULL pointer
     CPPUNIT_ASSERT_MESSAGE("check objet is ready", theObject->isReady());
  }
};
philippe
+1  A: 

Sorry to say this but the previous answers you received on this are ridiculous. cppunit really lacks in this regard. cppunit should implement an EXIT_ON_FAIL macro which allows you to trap the access violation in windows (using SetUnhandledExceptionFilter), then you can do any clean-up and allow cpp-unit to report the failure via EXIT_ON_FAIL. Then after reporting, exit the application.

A: 

As an additional note to anyone perusing this question later, I've found UnitTest++ can catch exceptions in tests and just fail the test with appropriate information rather than resulting in a process exit.

dlanod
A: 

I didn't try it, but if in Windows, I guess use SEH would help:

__try { // running your case }

__except { }

Integrate it into the CppUnit framework, and everytime receive an unknown exception, mark the case as fail.

lz_prgmr