Modulo [B]asico para prueba [unit]aria de programas:
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Valores de enumeraciones Amigas 'defines'
test_BUnit.cpp
Ir a la documentación de este archivo.
00001 // test_BUnit.cpp (C) 2006 adolfo@di-mare.com
00002 
00003 /** \file  test_BUnit.cpp
00004     \brief Test program form class \c BUnit.h
00005 
00006     \author Adolfo Di Mare <adolfo@di-mare.com>
00007     \date   2008
00008 */
00009 
00010 #include "BUnit.h"
00011 #include <iostream>
00012 using namespace std;
00013 
00014 /// Testing \c BUnit.h
00015 class test_BUnit : public TestCase {
00016 public:
00017     bool run();
00018     void test_constructor();
00019     void test_reset();
00020     void test_addTest();
00021     void test_run();
00022     void test_setName();
00023     void test_testThis();
00024     void test_BUnit_macro();
00025     void test_assertTrue_Msg();
00026     void test_Allison();
00027 };
00028 
00029 /// Main testing method.
00030 bool test_BUnit::run() {
00031     test_constructor();
00032     test_reset();
00033     test_addTest();
00034     test_run();
00035     test_setName();
00036     test_testThis();
00037     test_BUnit_macro();
00038     test_assertTrue_Msg();
00039     test_Allison();
00040 
00041     return wasSuccessful();
00042 }
00043 
00044 /// test_BUnit ==> \c TestCase::TestCase(...).
00045 void test_BUnit::test_constructor() {
00046     {{  // test::constructor()
00047         test_BUnit thisTest;
00048         assertTrue( string::npos != thisTest.getName().find( "test_BUnit" ) );
00049         assertTrue( thisTest.failureCount() == 0 );
00050         assertTrue( thisTest.countTestCases() == 1 );
00051         assertTrue( thisTest.successCount() == 0 );
00052         assertTrue( thisTest.runCount() == 0 );
00053         assertTrue( thisTest.failureString() == "" );
00054     }}
00055     {   // Remaining tests
00056         test_BUnit thisTest;
00057         assertTrue( thisTest.m_pass == 0 );
00058         assertTrue( thisTest.m_failure == 0 );
00059         assertTrue( thisTest.m_name == 0 );
00060         assertTrue( thisTest.m_failureList.empty() );
00061     }
00062 }
00063 
00064 /// test_BUnit ==> \c TestCase::reset() + \c TestCase::resetTests().
00065 void test_BUnit::test_reset() {
00066     {{  // test::reset()
00067         class MyTest : public TestCase {
00068         public:
00069             bool run() {
00070                 assertTrue( 1 == 2 ); // Failure !!!
00071                 assertTrue( 1 == 1 ); // Ok
00072                 assertTrue( 2 == 2 ); // Ok
00073                 return wasSuccessful();
00074             }
00075         }; // MyTest
00076         MyTest thisTest;
00077         for ( int i=0; i<11; ++i ) {
00078             thisTest.run(); // runs the same test 11 times
00079         }
00080         assertTrue( 11 == thisTest.failureCount() );   // ( 1 == 2 ) x 11
00081         assertTrue( 22 == thisTest.successCount() ); // ( 1 == 1 ) && ( 2 == 2 )
00082         assertTrue( 33 == thisTest.runCount() );     // 33 == 11+22
00083         assertTrue( "" != thisTest.failureString() );  // 11 recorded failures
00084         std::string remember = thisTest.getName();
00085 
00086         thisTest.reset(); // Anula los contadores
00087 
00088         assertTrue( 0 == thisTest.failureCount() );
00089         assertTrue( 0 == thisTest.successCount() );
00090         assertTrue( 0 == thisTest.runCount() );
00091         assertTrue( "" == thisTest.failureString() );
00092         assertTrue( remember == thisTest.getName() ); // reset() won´t change the name
00093     }}
00094 }
00095 
00096 /// test_BUnit ==> \c TestSuite<TestCase>::addTest().
00097 void test_BUnit::test_addTest() {
00098     {{  // test::addTest()
00099         class MyTest : public TestCase {
00100         public:
00101             bool run() {
00102                 assertTrue( 1 == 1 ); // Ok
00103                 assertTrue( 1 == 2 ); // Failure !!!
00104                 return wasSuccessful();
00105             }
00106         }; // MyTest
00107         TestSuite<TestCase> SSS;
00108         MyTest thisTest, *ptr_test = new MyTest;
00109         SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() will NOT destroy "thisTest"
00110         SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() WILL     destroy "ptr_test"
00111         assertTrue( 0 == SSS.failureCount() );
00112         SSS.run();
00113         assertTrue( 1+1 == SSS.failureCount() );
00114         assertTrue( "" != SSS.toXML() );
00115 
00116         TestSuite<TestCase> TTT, RRR;
00117         TTT.addTest( & SSS ); // similar to TTT.addSuite( SSS )
00118         assertTrue( "" == SSS.toXML() );
00119         assertTrue( "" != TTT.toXML() );
00120         RRR.addTest( TTT );   // similar to RRR.addSuite( TTT )
00121         assertTrue( 0 == SSS.countTestCases() );
00122         assertTrue( 0 == TTT.countTestCases() ); // SSS y TTT become "empty"
00123         assertTrue( 2 == RRR.countTestCases() );
00124         assertTrue( 2 == RRR.failureCount() );   // RRR has it all
00125         assertTrue( "" != RRR.toXML() );
00126     }}
00127     {   // Remaining tests
00128         class MyTest : public TestCase {
00129         public:
00130             bool run() {
00131                 assertTrue( 1 == 1 ); // Ok
00132                 assertTrue( 1 == 2 ); // Failure !!!
00133                 return wasSuccessful();
00134             }
00135         }; // MyTest
00136         TestSuite<TestCase> SSS, TTT;
00137         MyTest thisTest, *ptr_test = new MyTest;
00138         SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() won´t destroy "thisTest"
00139         SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() will detroy "ptr_test"
00140         SSS.addTest( ptr_test ); // no duplicates get added
00141         SSS.addTest( ptr_test ); // no duplicates get added
00142         SSS.addTest( (MyTest*)(0) ); // null never get added
00143         SSS.run();
00144         assertTrue( 2 == SSS.countTestCases() );
00145         assertTrue( 1+1 == SSS.failureCount() ); // 1 failure for each "TestCase"
00146 
00147         TTT.addSuite( *( (TestSuite<TestCase>*)(0) ) );
00148         TTT.addSuite( TTT ); // no se auto-aniquila
00149         assertTrue( 0 == TTT.countTestCases() );
00150 
00151         TTT.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() won´t destroy "thisTest"
00152         TTT.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() will detroy "ptr_test"
00153         assertTrue( 2 == TTT.countTestCases() );
00154 
00155         SSS.addTest( new MyTest );
00156         TTT.addSuite( SSS ); /// SSS se queda vacío
00157         TTT.addSuite( TTT ); TTT.addTest( TTT );  TTT.addTest( & TTT );
00158         assertTrue( 0 == SSS.countTestCases() );  // original empty
00159         assertTrue( 3 == TTT.countTestCases() );  // no duplicates
00160 
00161         TTT.run( ); // ads 3 failures to the previous 2
00162         assertTrue( 000 == SSS.failureCount() );
00163         assertTrue( 2+3 == TTT.failureCount() );
00164         thisTest.run();
00165         assertTrue( 1+2+3 == TTT.failureCount() );
00166     }
00167 }
00168 
00169 /// test_BUnit ==> \c run() + \c runBare().
00170 void test_BUnit::test_run() {
00171     {{  // test::run()
00172         class MyTest : public TestCase {
00173             int m_val;
00174         public:
00175             MyTest() : m_val(0) {} // init: m_val == 0;
00176             void setUp() { m_val = 1; }
00177             void tearDown() { m_val = 2; }
00178             bool run() {
00179                 assertTrue( m_val == 1 );
00180                 return wasSuccessful();
00181             }
00182         }; // MyTest
00183         TestSuite<TestCase> SSS;
00184         SSS.addTest( new MyTest );  SSS.addTest( new MyTest );
00185         assertTrue( 2 == SSS.countTestCases() );
00186         assertTrue( "" == SSS.failureString() );
00187 
00188         SSS.runBare(); // Ok ==> setUp() sets [m_val == 1]
00189         assertTrue( "" == SSS.toXML() );
00190 
00191         SSS.run();  // Failure: [m_val == 2] ==> value set by tearDown()
00192         std::string sssXML = SSS.toXML();
00193         assertTrue( "" != sssXML ); // SSS contains failures.
00194         assertTrue( sssXML.find("m_val") != string::npos );
00195         assertTrue( SSS.runCount() == 2+2 );
00196     }}
00197 }
00198 
00199 /// test_BUnit ==> \c getName() + \c setName().
00200 void test_BUnit::test_setName() {
00201     {{  // test::setName()
00202         class MyTest : public TestCase {
00203         public:
00204             bool run() {
00205                 assertTrue( 2 == 2 );
00206                 return wasSuccessful();
00207             }
00208         }; // MyTest
00209         MyTest thisTest;
00210         assertTrue(       "chorlito" != thisTest.getName() );
00211         thisTest.setName( "chorlito" );
00212         assertTrue(       "chorlito" == thisTest.getName() );
00213         {
00214         //  thisTest.setName( std::string("chorlito") ); // won´t compile
00215             thisTest.setName( std::string("chorlito").c_str() ); // bad practice
00216             std::string V("boom!");
00217             assertTrue( 0==strcmp( V.c_str() , "boom!") );
00218             assertTrue( "chorlito" != thisTest.getName() ); // c_str() uses
00219             assertTrue( "boom!"    == thisTest.getName() ); // static data
00220         }
00221     }}
00222 }
00223 
00224 /// test_BUnit ==> \c testThis().
00225 void test_BUnit::test_testThis() {
00226     {{  // test::testThis()
00227         class MyTest : public TestCase {
00228         public:
00229             bool run() {
00230                 bool dont_copy = false;
00231                 testThis( 2 == 2, "2 is 2", __FILE__, __LINE__, dont_copy ); // Ok
00232                 testThis( 1 == 2, "1 is 2", __FILE__, __LINE__, dont_copy ); // failure #1
00233                 testThis( 2 == 1, "2 is 1", __FILE__, __LINE__, dont_copy ); // failure #2
00234                 return wasSuccessful();
00235             }
00236         }; // MyTest
00237         MyTest thisTest;
00238         assertTrue( thisTest.wasSuccessful() ); // run() has not been executed
00239         thisTest.run(); // 2 failures
00240         assertTrue( thisTest.failureCount() == 2 );
00241         assertTrue( ! thisTest.wasSuccessful() );
00242     }}
00243 }
00244 
00245 #include <vector>    // std::vector
00246 #include <stdexcept> // std::logic_error
00247 
00248 /// test_BUnit ==> Macros.
00249 void test_BUnit::test_BUnit_macro() {
00250     {{  // test::BUnit_macro()
00251         class MyTest : public TestCase {
00252         public:
00253             bool run() {
00254                 testThis(   2 == 2, "2 == 2", __FILE__, __LINE__ );         // sucess
00255                 BUnit_TEST( 2 == 2 ); // same thing using macro BUnit_TEST()
00256                 testThis(   1 == 2, "1 == 2", __FILE__, __LINE__ );         // failure #1
00257                 assertTrue( 1 == 2 ); // same thing using BUnit_TEST()      // failure #2
00258                 {   // con macros
00259                     std::vector<int> V; // "V[]" is empty ==> there is no "V[2]"
00260                     try {
00261                         int i = V.at(2);  // "V[2]" does not exits
00262                         BUnit_FAILURE("V.at(2)"); // failure: "at()" didn´t rise the exception
00263                     }
00264                     catch (std::logic_error&) {
00265                         BUnit_SUCCESS(); // correct: "V.at(2)" throws "logic_error"
00266                     }                    // because "V[]" is empty
00267                 }
00268                 {   // no macros
00269                     std::vector<int> V;
00270                     try {
00271                         int i = V.at(2);
00272                         recordFailure("V.at(2)" , __FILE__ , __LINE__ );
00273                     }
00274                     catch (std::logic_error&) {
00275                         recordSuccess();
00276                     }
00277                 }
00278                 return wasSuccessful(); // Returns "false"
00279             }
00280         }; // MyTest
00281         MyTest thisTest;
00282         assertTrue( thisTest.wasSuccessful() ); // run() has not been executed
00283         thisTest.run(); // 2 failures
00284         assertTrue( thisTest.failureCount() == 2 );
00285         assertTrue( thisTest.toXML() != "" );
00286         assertTrue( ! thisTest.wasSuccessful() );
00287     }}
00288 }
00289 
00290 /// test_BUnit ==> \c assertTrue_Msg().
00291 void test_BUnit::test_assertTrue_Msg() {
00292     {{  // test::assertTrue_Msg()
00293         class MyTest : public TestCase {
00294             enum { N = 6 };
00295             int m_Matrix[N][N];
00296         public:
00297             void setUp() {
00298                 for ( int i=0; i<N; ++i ) {
00299                     for ( int j=0; j<N; ++j ) {
00300                         m_Matrix[i][j] = 666;
00301                     }
00302                 }
00303             }
00304             bool run() {
00305                 for ( int i=0; i<N; ++i ) {
00306                     for ( int j=0; j<N; ++j ) {
00307                         std::string err = "m_Matrix";
00308                         err += '[' + TestCase::toString(i) + ']';
00309                         err += '[' + TestCase::toString(j) + ']';
00310                         err += " == 0";
00311                         assertTrue_Msg( err , m_Matrix[i][j] == 0 );
00312                     }
00313                 }
00314                 return wasSuccessful();
00315             }
00316         }; // MyTest
00317         MyTest tester;
00318         tester.runBare();
00319         assertTrue( ! tester.wasSuccessful() );
00320         // nunca agrega el mensaje genérico "m_Matrix[i][j] == 0"
00321         assertTrue( string::npos == tester.toString().find( "m_Matrix[i][j] == 0" ) );
00322         // siempre usa el mensaje específico en el valor de "i-j"
00323         assertTrue( string::npos != tester.toString().find( "m_Matrix[3][5] == 0" ) );
00324     }}
00325 }
00326 
00327 #include <exception> // std::out_of_range
00328 
00329 // La especificiacién está más adelantes.
00330 void test_BUnit::test_Allison() {
00331     {{  // test::Allison()
00332         // Stack class for letter -- very simple (<em>Last In First Out</em>).
00333         // - Throws \c std::logic_error on invalid operations.
00334         // - Example inspired in Chuck Allison' work.
00335         // - http://search.yahoo.com/search?n=100&p=Simplest+Unit+Test+Allison
00336         class Stack {
00337         public:
00338             enum { N = 5 /* Max Capacity for the stack */ };
00339             // Constructor for a stack that can hold up to \c "Stack::N" values.
00340             Stack() : m_top(0) { m_vec[m_top] = 0; }
00341             // Stoes a copy of "v" at the top of the stack.
00342             void push(const char& v) {
00343                 if ( m_top != N ) { m_vec[m_top] = v; m_top++; }
00344                 else { throw std::out_of_range("Stack::push()"); }
00345             }
00346             // Removes the topmost value from the stack.
00347             void pop() {
00348                 if ( m_top>0 ) { m_top--; }
00349                 else { throw std::out_of_range("Stack::pop()"); }
00350             }
00351             // Reference to topmost value in the stack.
00352             char& top() {
00353                 if ( m_top>0 ) { return m_vec[m_top-1]; }
00354                 else { throw std::out_of_range("Stack::top()"); }
00355             }
00356             // Number of values stored in the stack.
00357             unsigned size() const { return m_top; }
00358         private:
00359             char m_vec[N+1] ; // Vector to hold stored values.
00360             int  m_top;       // Next available vector entry.
00361         }; // Stack
00362 
00363         class MyTest : public TestCase {
00364         public:
00365             bool run() {
00366                 Stack S; // the stack
00367 
00368                 try { // empty stack
00369                     S.pop();
00370                     fail_Msg("! S.pop()");
00371                 }
00372                 catch ( std::out_of_range & ex ) {
00373                     assertTrue( 0 == strcmp( ex.what() , "Stack::pop()" ) ); // Ok: empty stack
00374                 }
00375                 catch (...) {
00376                     fail_Msg("! ( std::out_of_range & )");
00377                 }
00378 
00379                 try { // Pila llena
00380                     for (int i=0; true; ++i) {
00381                         S.push('0'+i);
00382                         assertTrue( S.top() == '0'+i );
00383                     }
00384                     fail_Msg("! S.push()");
00385                 }
00386                 catch ( std::out_of_range & ex ) {
00387                     assertTrue( 0 == strcmp( ex.what() , "Stack::push()" ) ); // Ok: full stack
00388                 }
00389                 catch (...) {
00390                     fail_Msg("! ( std::out_of_range & )");
00391                 }
00392 
00393                 try { // Vacea la pila
00394                     for (int i=Stack::N-1; true; --i) {
00395                         assertTrue( S.top() == '0'+i );
00396                         S.pop();
00397                     }
00398                     fail_Msg("! S.pop()");
00399                 }
00400                 catch ( std::out_of_range & ex ) {
00401                     assertTrue( 0 == strcmp( ex.what() , "Stack::top()" ) ); // Ok: empty stack
00402                 }
00403                 catch (...) {
00404                     fail_Msg("! ( std::out_of_range & )");
00405                 }
00406                 return wasSuccessful();
00407             }
00408         }; // MyTest
00409         MyTest thisTest;
00410         thisTest.run(); // 0 failures
00411         assertTrue( thisTest.wasSuccessful() );
00412     }}
00413 }
00414 
00415 // could not put this specification before because \skipline would find it first
00416 /** \fn    void test_BUnit::test_Allison();
00417     \brief test_BUnit ==> \c test_Allison().
00418 
00419     \dontinclude test_BUnit.cpp
00420     \skipline    test::Allison()
00421     \until       }}
00422     \see         test_BUnit::test_Allison()
00423 */
00424 
00425 /// Main program ==> excecutes all tests.
00426 int main() {
00427     if (1) {
00428         test_BUnit test_BUnit_Instance;
00429         test_BUnit_Instance.setUp();
00430         test_BUnit_Instance.run();
00431         cout << test_BUnit_Instance.summary() << endl;
00432         cout << test_BUnit_Instance.toString() << endl;
00433         cout << test_BUnit_Instance.toXML() << endl;
00434 
00435         TestSuite<TestCase> SSS;
00436         SSS.addTest( test_BUnit_Instance );
00437         SSS.addTest( new test_BUnit );
00438         SSS.run();
00439         cout << SSS.report() << endl;
00440         cout << SSS.toXML() << endl;
00441 
00442         TestSuite<TestCase> TTT;
00443         TTT.addTest( SSS );
00444         TTT.run();
00445         cout << TTT.summary() << endl;
00446         cout << TTT.toString() << endl;
00447     }
00448     return 0;
00449 }
00450 
00451 // EOF: test_BUnit.cpp