// test_BUnit.cpp (C) 2006 adolfo@di-mare.com /** \file test_BUnit.cpp \brief Test program form class \c BUnit.h \author Adolfo Di Mare \date 2008 */ #include "BUnit.h" #include using namespace std; /// Testing \c BUnit.h class test_BUnit : public TestCase { public: bool run(); void test_constructor(); void test_reset(); void test_addTest(); void test_run(); void test_setName(); void test_testThis(); void test_BUnit_macro(); void test_assertTrue_Msg(); void test_Allison(); }; /// Main testing method. bool test_BUnit::run() { test_constructor(); test_reset(); test_addTest(); test_run(); test_setName(); test_testThis(); test_BUnit_macro(); test_assertTrue_Msg(); test_Allison(); return wasSuccessful(); } /// test_BUnit ==> \c TestCase::TestCase(...). void test_BUnit::test_constructor() { {{ // test::constructor() test_BUnit thisTest; assertTrue( string::npos != thisTest.getName().find( "test_BUnit" ) ); assertTrue( thisTest.failureCount() == 0 ); assertTrue( thisTest.countTestCases() == 1 ); assertTrue( thisTest.successCount() == 0 ); assertTrue( thisTest.runCount() == 0 ); assertTrue( thisTest.failureString() == "" ); }} { // Remaining tests test_BUnit thisTest; assertTrue( thisTest.m_pass == 0 ); assertTrue( thisTest.m_failure == 0 ); assertTrue( thisTest.m_name == 0 ); assertTrue( thisTest.m_failureList.empty() ); } } /// test_BUnit ==> \c TestCase::reset() + \c TestCase::resetTests(). void test_BUnit::test_reset() { {{ // test::reset() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 2 ); // Failure !!! assertTrue( 1 == 1 ); // Ok assertTrue( 2 == 2 ); // Ok return wasSuccessful(); } }; // MyTest MyTest thisTest; for ( int i=0; i<11; ++i ) { thisTest.run(); // runs the same test 11 times } assertTrue( 11 == thisTest.failureCount() ); // ( 1 == 2 ) x 11 assertTrue( 22 == thisTest.successCount() ); // ( 1 == 1 ) && ( 2 == 2 ) assertTrue( 33 == thisTest.runCount() ); // 33 == 11+22 assertTrue( "" != thisTest.failureString() ); // 11 recorded failures std::string remember = thisTest.getName(); thisTest.reset(); // Anula los contadores assertTrue( 0 == thisTest.failureCount() ); assertTrue( 0 == thisTest.successCount() ); assertTrue( 0 == thisTest.runCount() ); assertTrue( "" == thisTest.failureString() ); assertTrue( remember == thisTest.getName() ); // reset() won´t change the name }} } /// test_BUnit ==> \c TestSuite::addTest(). void test_BUnit::test_addTest() { {{ // test::addTest() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite SSS; MyTest thisTest, *ptr_test = new MyTest; SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() will NOT destroy "thisTest" SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() WILL destroy "ptr_test" assertTrue( 0 == SSS.failureCount() ); SSS.run(); assertTrue( 1+1 == SSS.failureCount() ); assertTrue( "" != SSS.toXML() ); TestSuite TTT, RRR; TTT.addTest( & SSS ); // similar to TTT.addSuite( SSS ) assertTrue( "" == SSS.toXML() ); assertTrue( "" != TTT.toXML() ); RRR.addTest( TTT ); // similar to RRR.addSuite( TTT ) assertTrue( 0 == SSS.countTestCases() ); assertTrue( 0 == TTT.countTestCases() ); // SSS y TTT become "empty" assertTrue( 2 == RRR.countTestCases() ); assertTrue( 2 == RRR.failureCount() ); // RRR has it all assertTrue( "" != RRR.toXML() ); }} { // Remaining tests class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite SSS, TTT; MyTest thisTest, *ptr_test = new MyTest; SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() won´t destroy "thisTest" SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() will detroy "ptr_test" SSS.addTest( ptr_test ); // no duplicates get added SSS.addTest( ptr_test ); // no duplicates get added SSS.addTest( (MyTest*)(0) ); // null never get added SSS.run(); assertTrue( 2 == SSS.countTestCases() ); assertTrue( 1+1 == SSS.failureCount() ); // 1 failure for each "TestCase" TTT.addSuite( *( (TestSuite*)(0) ) ); TTT.addSuite( TTT ); // no se auto-aniquila assertTrue( 0 == TTT.countTestCases() ); TTT.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() won´t destroy "thisTest" TTT.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() will detroy "ptr_test" assertTrue( 2 == TTT.countTestCases() ); SSS.addTest( new MyTest ); TTT.addSuite( SSS ); /// SSS se queda vacío TTT.addSuite( TTT ); TTT.addTest( TTT ); TTT.addTest( & TTT ); assertTrue( 0 == SSS.countTestCases() ); // original empty assertTrue( 3 == TTT.countTestCases() ); // no duplicates TTT.run( ); // ads 3 failures to the previous 2 assertTrue( 000 == SSS.failureCount() ); assertTrue( 2+3 == TTT.failureCount() ); thisTest.run(); assertTrue( 1+2+3 == TTT.failureCount() ); } } /// test_BUnit ==> \c run() + \c runBare(). void test_BUnit::test_run() { {{ // test::run() class MyTest : public TestCase { int m_val; public: MyTest() : m_val(0) {} // init: m_val == 0; void setUp() { m_val = 1; } void tearDown() { m_val = 2; } bool run() { assertTrue( m_val == 1 ); return wasSuccessful(); } }; // MyTest TestSuite SSS; SSS.addTest( new MyTest ); SSS.addTest( new MyTest ); assertTrue( 2 == SSS.countTestCases() ); assertTrue( "" == SSS.failureString() ); SSS.runBare(); // Ok ==> setUp() sets [m_val == 1] assertTrue( "" == SSS.toXML() ); SSS.run(); // Failure: [m_val == 2] ==> value set by tearDown() std::string sssXML = SSS.toXML(); assertTrue( "" != sssXML ); // SSS contains failures. assertTrue( sssXML.find("m_val") != string::npos ); assertTrue( SSS.runCount() == 2+2 ); }} } /// test_BUnit ==> \c getName() + \c setName(). void test_BUnit::test_setName() { {{ // test::setName() class MyTest : public TestCase { public: bool run() { assertTrue( 2 == 2 ); return wasSuccessful(); } }; // MyTest MyTest thisTest; assertTrue( "chorlito" != thisTest.getName() ); thisTest.setName( "chorlito" ); assertTrue( "chorlito" == thisTest.getName() ); { // thisTest.setName( std::string("chorlito") ); // won´t compile thisTest.setName( std::string("chorlito").c_str() ); // bad practice std::string V("boom!"); assertTrue( 0==strcmp( V.c_str() , "boom!") ); assertTrue( "chorlito" != thisTest.getName() ); // c_str() uses assertTrue( "boom!" == thisTest.getName() ); // static data } }} } /// test_BUnit ==> \c testThis(). void test_BUnit::test_testThis() { {{ // test::testThis() class MyTest : public TestCase { public: bool run() { bool dont_copy = false; testThis( 2 == 2, "2 is 2", __FILE__, __LINE__, dont_copy ); // Ok testThis( 1 == 2, "1 is 2", __FILE__, __LINE__, dont_copy ); // failure #1 testThis( 2 == 1, "2 is 1", __FILE__, __LINE__, dont_copy ); // failure #2 return wasSuccessful(); } }; // MyTest MyTest thisTest; assertTrue( thisTest.wasSuccessful() ); // run() has not been executed thisTest.run(); // 2 failures assertTrue( thisTest.failureCount() == 2 ); assertTrue( ! thisTest.wasSuccessful() ); }} } #include // std::vector #include // std::logic_error /// test_BUnit ==> Macros. void test_BUnit::test_BUnit_macro() { {{ // test::BUnit_macro() class MyTest : public TestCase { public: bool run() { testThis( 2 == 2, "2 == 2", __FILE__, __LINE__ ); // sucess BUnit_TEST( 2 == 2 ); // same thing using macro BUnit_TEST() testThis( 1 == 2, "1 == 2", __FILE__, __LINE__ ); // failure #1 assertTrue( 1 == 2 ); // same thing using BUnit_TEST() // failure #2 { // con macros std::vector V; // "V[]" is empty ==> there is no "V[2]" try { int i = V.at(2); // "V[2]" does not exits BUnit_FAILURE("V.at(2)"); // failure: "at()" didn´t rise the exception } catch (std::logic_error&) { BUnit_SUCCESS(); // correct: "V.at(2)" throws "logic_error" } // because "V[]" is empty } { // no macros std::vector V; try { int i = V.at(2); recordFailure("V.at(2)" , __FILE__ , __LINE__ ); } catch (std::logic_error&) { recordSuccess(); } } return wasSuccessful(); // Returns "false" } }; // MyTest MyTest thisTest; assertTrue( thisTest.wasSuccessful() ); // run() has not been executed thisTest.run(); // 2 failures assertTrue( thisTest.failureCount() == 2 ); assertTrue( thisTest.toXML() != "" ); assertTrue( ! thisTest.wasSuccessful() ); }} } /// test_BUnit ==> \c assertTrue_Msg(). void test_BUnit::test_assertTrue_Msg() { {{ // test::assertTrue_Msg() class MyTest : public TestCase { enum { N = 6 }; int m_Matrix[N][N]; public: void setUp() { for ( int i=0; i // std::out_of_range // La especificiacién está más adelantes. void test_BUnit::test_Allison() { {{ // test::Allison() // Stack class for letter -- very simple (Last In First Out). // - Throws \c std::logic_error on invalid operations. // - Example inspired in Chuck Allison' work. // - http://search.yahoo.com/search?n=100&p=Simplest+Unit+Test+Allison class Stack { public: enum { N = 5 /* Max Capacity for the stack */ }; // Constructor for a stack that can hold up to \c "Stack::N" values. Stack() : m_top(0) { m_vec[m_top] = 0; } // Stoes a copy of "v" at the top of the stack. void push(const char& v) { if ( m_top != N ) { m_vec[m_top] = v; m_top++; } else { throw std::out_of_range("Stack::push()"); } } // Removes the topmost value from the stack. void pop() { if ( m_top>0 ) { m_top--; } else { throw std::out_of_range("Stack::pop()"); } } // Reference to topmost value in the stack. char& top() { if ( m_top>0 ) { return m_vec[m_top-1]; } else { throw std::out_of_range("Stack::top()"); } } // Number of values stored in the stack. unsigned size() const { return m_top; } private: char m_vec[N+1] ; // Vector to hold stored values. int m_top; // Next available vector entry. }; // Stack class MyTest : public TestCase { public: bool run() { Stack S; // the stack try { // empty stack S.pop(); fail_Msg("! S.pop()"); } catch ( std::out_of_range & ex ) { assertTrue( 0 == strcmp( ex.what() , "Stack::pop()" ) ); // Ok: empty stack } catch (...) { fail_Msg("! ( std::out_of_range & )"); } try { // Pila llena for (int i=0; true; ++i) { S.push('0'+i); assertTrue( S.top() == '0'+i ); } fail_Msg("! S.push()"); } catch ( std::out_of_range & ex ) { assertTrue( 0 == strcmp( ex.what() , "Stack::push()" ) ); // Ok: full stack } catch (...) { fail_Msg("! ( std::out_of_range & )"); } try { // Vacea la pila for (int i=Stack::N-1; true; --i) { assertTrue( S.top() == '0'+i ); S.pop(); } fail_Msg("! S.pop()"); } catch ( std::out_of_range & ex ) { assertTrue( 0 == strcmp( ex.what() , "Stack::top()" ) ); // Ok: empty stack } catch (...) { fail_Msg("! ( std::out_of_range & )"); } return wasSuccessful(); } }; // MyTest MyTest thisTest; thisTest.run(); // 0 failures assertTrue( thisTest.wasSuccessful() ); }} } // could not put this specification before because \skipline would find it first /** \fn void test_BUnit::test_Allison(); \brief test_BUnit ==> \c test_Allison(). \dontinclude test_BUnit.cpp \skipline test::Allison() \until }} \see test_BUnit::test_Allison() */ /// Main program ==> excecutes all tests. int main() { if (1) { test_BUnit test_BUnit_Instance; test_BUnit_Instance.setUp(); test_BUnit_Instance.run(); cout << test_BUnit_Instance.summary() << endl; cout << test_BUnit_Instance.toString() << endl; cout << test_BUnit_Instance.toXML() << endl; TestSuite SSS; SSS.addTest( test_BUnit_Instance ); SSS.addTest( new test_BUnit ); SSS.run(); cout << SSS.report() << endl; cout << SSS.toXML() << endl; TestSuite TTT; TTT.addTest( SSS ); TTT.run(); cout << TTT.summary() << endl; cout << TTT.toString() << endl; } return 0; } // EOF: test_BUnit.cpp