Thread: [Cppunit-devel] hierarchy sample bug...
Brought to you by:
blep
From: Baptiste L. <bl...@cl...> - 2001-05-05 21:43:11
|
Well, another stuff to clean up would be that one. There is a well hidden bug in this sample dealing with hiearchy: In the template BoardGameTest: virtual void registerTests(CppUnit::TestSuite *suite) { suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", &BoardGameTest<GAMECLASS>::testReset)); suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", &BoardGameTest<GAMECLASS>::testResetShouldFail)); } => BoardGameTest class will be instantiated by each test caller. and: class ChessTest : public BoardGameTest<GAMECLASS> { ... void registerTests(CppUnit::TestSuite *suite) { BoardGameTest<GAMECLASS>::registerTests(suite); suite->addTest ( new CppUnit::TestCaller<ChessTest> ("testNumberOfPieces", &ChessTest<GAMECLASS>::testNumberOfPieces)); } => for ChessTest we have the parent class test caller instantiating BoardGameTest instead of ChessTest !!!! The way I found to correct this is to make registerTests() a template member :-(. This is done in the HelperMacros as follow: static CppUnit::Test *suite() __ThisTestCaseType *test =NULL; CppUnit::TestSuiteBuilder<__ThisTestCaseType> suite; __ThisTestCaseType::registerTests( suite, test ); return suite.takeSuite(); } template<class TestCaseType> static void registerTests( CppUnit::TestSuiteBuilder<TestCaseType> &suite, TestCaseType *test ) { __ThisSuperClassType::registerTests( suite, test ) ... } At the current time, I haven't found any easier way to to this :-(. Any ideas ? Baptiste. --- Baptiste Lepilleur <gai...@fr...> http://gaiacrtn.free.fr/index.html Author of The Text Reformatter, a tool for fanfiction readers and writers. Language: English, French (Well, I'm French). |
From: Bastiaan B. <bas...@li...> - 2001-05-06 00:48:24
|
Baptiste Lepilleur wrote: > Well, another stuff to clean up would be that one. There is a well > hidden bug in this sample dealing with hiearchy: > > In the template BoardGameTest: > > virtual void registerTests(CppUnit::TestSuite *suite) > { > suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", > &BoardGameTest<GAMECLASS>::testReset)); > suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", > &BoardGameTest<GAMECLASS>::testResetShouldFail)); > } > => BoardGameTest class will be instantiated by each test caller. > > and: > class ChessTest : public BoardGameTest<GAMECLASS> { > ... > void registerTests(CppUnit::TestSuite *suite) > { > BoardGameTest<GAMECLASS>::registerTests(suite); > suite->addTest ( > new CppUnit::TestCaller<ChessTest> ("testNumberOfPieces", > &ChessTest<GAMECLASS>::testNumberOfPieces)); > } > => for ChessTest we have the parent class test caller instantiating > BoardGameTest instead of ChessTest !!!! > That is correct behaviour. The BoardGameTest checks invariants that should hold for all BoardGameTest instances, including Chess objects. The testReset() method in BoardGameTest should equally apply to Chess objects. Overriding testReset() in ChessTest is a serious indication that the design of application is flawed. However, there is one problem, which may be what you hint at: the current BoardGameTest implementation implies that all BoardGame classes have a default constructor and need no further setup. Lemme think this over. Bye, Bastiaan > > The way I found to correct this is to make registerTests() a template member > :-(. This is done in the HelperMacros as follow: > > static CppUnit::Test *suite() > > __ThisTestCaseType *test =NULL; > CppUnit::TestSuiteBuilder<__ThisTestCaseType> suite; > __ThisTestCaseType::registerTests( suite, test ); > return suite.takeSuite(); > } > > template<class TestCaseType> > static void > registerTests( CppUnit::TestSuiteBuilder<TestCaseType> &suite, > TestCaseType *test ) > { > __ThisSuperClassType::registerTests( suite, test ) > ... > } > > At the current time, I haven't found any easier way to to this :-(. Any > ideas ? > > Baptiste. > > --- > Baptiste Lepilleur <gai...@fr...> http://gaiacrtn.free.fr/index.html > Author of The Text Reformatter, a tool for fanfiction readers and writers. > Language: English, French (Well, I'm French). > > _______________________________________________ > Cppunit-devel mailing list > Cpp...@li... > http://lists.sourceforge.net/lists/listinfo/cppunit-devel |
From: Baptiste L. <bl...@cl...> - 2001-05-07 08:46:20
|
> Baptiste Lepilleur wrote: > > > Well, another stuff to clean up would be that one. There is a well > > hidden bug in this sample dealing with hiearchy: > > > > In the template BoardGameTest: > > > > virtual void registerTests(CppUnit::TestSuite *suite) > > { > > suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", > > &BoardGameTest<GAMECLASS>::testReset)); > > suite->addTest (new CppUnit::TestCaller<BoardGameTest> ("testReset", > > &BoardGameTest<GAMECLASS>::testResetShouldFail)); > > } > > => BoardGameTest class will be instantiated by each test caller. > > > > and: > > class ChessTest : public BoardGameTest<GAMECLASS> { > > ... > > void registerTests(CppUnit::TestSuite *suite) > > { > > BoardGameTest<GAMECLASS>::registerTests(suite); > > suite->addTest ( > > new CppUnit::TestCaller<ChessTest> ("testNumberOfPieces", > > &ChessTest<GAMECLASS>::testNumberOfPieces)); > > } > > => for ChessTest we have the parent class test caller instantiating > > BoardGameTest instead of ChessTest !!!! > > > > That is correct behaviour. The BoardGameTest checks invariants that should hold > for all BoardGameTest instances, including Chess objects. The testReset() > method in BoardGameTest should equally apply to Chess objects. Overriding > testReset() in ChessTest is a serious indication that the design of application > is flawed. I agree with that. Though in some case you might have some "template method" (the pattern) in your test case. I can see that applying when you have some specific behavior and want to factor some testing part. An example that pop up into my mind would be testing visitor/strategy/builder. The setup of each test may be identical and you would want to factor out those part in a base class. Then, you would use the self-shunt pattern (having the test case implementing the visitor interface...), and delegate part of the actual test to the derived test case. > However, there is one problem, which may be what you hint at: the current > BoardGameTest implementation implies that all BoardGame classes have a default > constructor and need no further setup. This is indeed the main problem I see. You want the setUp() and tearOff() method of your derived class to be called: initialization of the "game" class, initialization of the default database connection for the current thread... Baptiste. --- Baptiste Lepilleur <gai...@fr...> http://gaiacrtn.free.fr/index.html Author of The Text Reformatter, a tool for fanfiction readers and writers. Language: English, French (Well, I'm French). |