[Cppunit-devel] TestCase that expect exception...
Brought to you by:
blep
From: Baptiste L. <gai...@fr...> - 2001-09-24 15:27:31
|
Well, starting on new stuff functionnalities agin... TestCaller provides a way to expect macro. Yesterday I try to had a new macro: CPPUNIT_TEST_EXCEPTION( method, ExceptionType), that would construct a TestCaller that would expect the specified method to throw an exception. I remembered the discussion we had about using a decorator to do that. I tried to create such a thing, but... What we want to decorate is TestCase::runTest(). Ideally we would create a ExceptionTestCase class that would decorate a TestCase, and forward setUp(), tearDown() to that testcase, and implement runTest() by forwarding to the testcase's runTest(), but expecting it to throw the exception. The problem is that TestCase is using the TemplateMethod pattern and runTest () is protected. So I fell back on the current solution on use the TestCaller to do that. But that raise the inconsistancy issue between the testcaller (can expect exception), and the testcase. I also needed to add a template method to TestSuiteBuilder (with a dummy pointer to pass the exception type). Notes that I'll probably add another macro: CPPUNIT_TEST_FAIL( method ), which expand to CPPUNIT_TEST_EXCEPTION( method, CppUnit::Exception). That one is actually of use when you test testing classes (you write an utility class that compare some expected and actual data structure, and is complicated enough that you want to test it). For short term, I'll report the change using that solution (it's hidden behind macros) to the CVS tree when the branch is done. Let's talk about long term... The core of the problem is that the only way to change the behavior of TestCase::runTest() is by subclassing. This go with another issue I have: I want to be able to extend the framework to to include new recognized exception class in TestCase::run() (for example, using RogueWave library, you get RWXMsg as a base class instead of std::exception). An obvious way to do both would be able to pass a "decorator" to TestCase::run () that would be used to run the actual testcase: class TestCaseDecorator { public: virtual setUp( TestCase *test ); virtual runTest( TestCase *test ); virtual tearDown( TestCase *test ); }; TestCase::run( TestResult *result, TestCaseDecorator *decorator ) { // [...] try { decorator->setUp(); try { decorator->runTest(); } // [...] decoartor->tearDown(); } // [...] } The decorator would probably not be a paremeter. I could TestResult becoming something more than just "result", and handling a "stack" of decorator (you could push a decorator that would decorate all previous decorator). If we had something like this, we could: - handle new exception type. - handle "expected exception" using decorator: subclass Test, and push the decorator that expect the exception in run(), then call the decorated test run () method, pop the decorator. Baptiste. --- Baptiste Lepilleur <gai...@fr...> http://gaiacrtn.free.fr/index.html Language: English, French |