[B]asic module for [unit] program testing:
|
Test collection. More...
#include <BUnit.h>
Public Types | |
typedef std::list < TestCase_is_base_for_TestSuite * > | container_type |
Container type (choice your preferred). | |
typedef container_type::iterator | iterator |
Container iterador. | |
typedef const container_type::iterator | cons_iterator |
Container iterador (const ). | |
typedef const container_type | const_container_type |
Container type (const ). | |
Public Member Functions | |
TestSuite (const char *name=0) | |
Constructor. | |
virtual | ~TestSuite () |
Destructor. | |
bool | addTest (TestCase &T) |
Adds test "T" to collection "*this" (and later it will not be destroyed). | |
bool | addTest (TestCase *T) |
Adds test "*pT" to collection "*this" (and later it will be destroyed). | |
void | addSuite (TestSuite &SSS) |
Moves all test from collection "SSS" and ads them to "*this" . | |
bool | run () |
Invokes TestCase::run() for each test in the collection. | |
void | runBare () |
Invokes TestCase::runBare() for each test in the collection. | |
int | countTestCases () const |
Number of test cases. | |
int | failureCount () const |
Number of test runs that failed. | |
int | successCount () const |
Number of successful test runs. | |
void | reset () |
Discards all test runs. | |
const_container_type & | allTests () const |
Reference to the container where al the test runs are stored. | |
const std::string | toString () const |
Huuuge string that holds a copy of non successfull test, separated by "\n" . | |
const std::string | summary () const |
Returns a string with the name, number of successes and failures. | |
const std::string | toXML () const |
XML string that holds a copy of all unsuccessful tests. | |
bool | Run () |
Synonym for run() . | |
bool | runTest () |
Synonym for run() . | |
virtual void | setUp () |
Sets the environment for the test run. | |
virtual void | tearDown () |
Destroys the test environment. | |
int | runCount () const |
Number of test runs. | |
int | errorCount () const |
Always returns 0 (cero): "Number of errors". | |
bool | wasSuccessful () const |
Returns "true" when all test runs where successful. | |
std::string | getName () const |
Gets the test case name. | |
void | setName (const char *name=0) |
Sets the test case name to "name" . | |
const std::string | report () const |
Returns string summary() followed by toString() . | |
const std::string | failureString () const |
Synonym for toString() . | |
Static Public Member Functions | |
template<class T > | |
static std::string | toString (const T &val) |
Returns a std::string constructed form value val . | |
Protected Member Functions | |
void | recordSuccess () |
Records the test run as a success. | |
void | recordFailure (const char *label, const char *fname, int lineno, bool must_copy=false) |
Records that the test run did not succeed. | |
void | recordFailure (const std::string &label, const char *fname, int lineno) |
Records that the test did not succeed. | |
void | testThis (bool cond, const char *label, const char *fname, long lineno, bool must_copy=false) |
Executes the test and records its result. | |
void | testThis (bool cond, const std::string &label, const char *fname, long lineno) |
Synonym for testThis() . | |
int | nPass () const |
Synonym for successCount() [OBSOLETE]. | |
int | nError () const |
Synonym for failureCount() [OBSOLETE]. | |
Protected Attributes | |
int | m_pass |
Number of successful tests. | |
int | m_failure |
Number of test that produced failed. | |
const char * | m_name |
Test case name. | |
bool | m_test_suite_destroy |
Holds "true" if the test case is stored in dynamic memory. | |
std::list< TestCaseFailure > | m_failureList |
Container where test cases that produced failures are stored. | |
Private Member Functions | |
bool | iAmTestSuite () const |
Returns true only for derived class TestSuite<> . | |
TestSuite (const TestSuite &DONTcopy) | |
This "private" declaration forbids test case copying. | |
TestSuite & | operator= (const TestSuite &DONTcopy) |
This "private" declaration forbids test case copying. | |
Private Attributes | |
container_type | m_allTest |
Container to store pointers to tests. | |
Friends | |
class | TestSuite |
Colección de pruebas. | |
template<class TestCase > | |
void | do_toXML (const TestCase *tc, std::basic_ostringstream< char > &ost) |
Adds to ost the string of al unsuccessful test from *tc in XML format. | |
template<class TestCase > | |
void | do_toString (const TestCase *tc, std::basic_ostringstream< char > &ost) |
Adds to ost the string of al unsuccessful test from *tc . |
Test collection.
TestCase
.TestCase::run()
method.TestSuite<TestCase>::runBare()
is similar to TestSuite<TestCase>::run()
, but before each test the test environment for the test is established invoking TestCase::setUp()
and TestCase::tearDown()
afterwards.setUp()
and tearDown()
to exectute test in the collection, each tests becomes "isolated" from the rest, because each stablishes its execution environment promised by class TestCase
."BUnit.cpp"
, to allow program testis using a single include of file "BUnit.h"
."BUnit.cpp"
TestSuite<>
template I used as parameter identifier TestCase
, which is also the name for the class from where TestSuite<>
is derived. This dual use of the same identifier confuses the compiler, because it can not figure out that parameter TestCase
is also the name for the base class. Therefore, I use a synonym to name the base class for TestSuite<>
. I chose identifier TestCase_is_base_for_TestSuite
because it is descriptive and quite long, so it is very unlikely that client programmer of BUnit.h
would ever need to use it.TestSuite<>
is implemented using templates to avoid forcing the client programmer of "BUnit"
to use 2 files, a header file "BUnit.h"
and another to hold the implementation "BUnit.cpp."
As there is no need to use the file "BUnit.cpp"
, implementing test programs is easy because programming test cases only requires adding this single line:#include "BUnit.h"
"BUnit"
is contained in header file "BUnit.h"
, it may happen that some routines get duplicated in the object code when header file "BUnit.h"
is included from several different ".cpp"
files in the same project. In these cases, methods that are not "inline" are defined in several files and, consequently, the linkage editor ("linker") should report that the same object module is present in several object files. When templates are used, the compiling system is responsible for managing this duplicating what relieves the programmer of this cumbersome responsibility. This explains why TestSuite<>
is a template class."BUnit.cpp"
containing all definition for non "inline" functions.BUnit.h
to fit into a single file forces implementing TestSuite<>
with templates, which also motivates the use TestCase
as the name name of the parameter template TestSuite<>
.TestSuite<>
is implemented with templates is to ensure that the responsibility for removing duplicate functions and methods belongs to the compiling system, as otherwise the client programmers would be required to include in their proyect implementation file "BUnit.cpp"
, which would make more complicated using BUnit
. This programming trick puts the compiler in charge of handling the implementation coide that otherwise would have been put in an implementation file"BUnit.cpp."
template< class TestCase > typedef TestSuite< TestCase >::container_type |
template< class TestCase > typedef TestSuite< TestCase >::cons_iterator |
template< class TestCase > typedef TestSuite< TestCase >::const_container_type |
Destructor.
TestSuite<TestCase>::addTest(TestCase* T)
(pointer).TestSuite<TestCase>::addTest(TestCase& T)
(reference). template< class TestCase > TestSuite< TestCase >::TestSuite | ( | const TestSuite< TestCase > & | DONTcopy | ) | [private] |
This "private"
declaration forbids test case copying.
Adds test "T"
to collection "*this"
(and later it will not be destroyed).
"T"
when "*this"
is destroyed."T"
parameter is a reference."pT"
is a test colection the effect is similar to invoking addSuite(T)
directly. {{ // test::addTest() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite<TestCase> 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<TestCase> 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() ); }}
Adds test "*pT"
to collection "*this"
(and later it will be destroyed).
(pT == 0)
nothing is added and returns "false"
."*pT"
when "*this"
is destroyed."pT"
parameter is a pointer."pT"
is a test colection the effect is similar to invoking addSuite(*pT)
directly. {{ // test::addTest() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite<TestCase> 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<TestCase> 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() ); }}
void TestSuite< TestCase >::addSuite | ( | TestSuite< TestCase > & | SSS | ) | [inline] |
Moves all test from collection "SSS"
and ads them to "*this"
.
"SSS"
empty.SSS
to avoid problems that come up when both "SSS"
and "*this"
try to destroy the same test.Invokes TestCase::run()
for each test in the collection.
TestCase::setUp()
and TestCase::tearDown()
when executing each test.TestSuite<TestCase>::reset()
before each test."true"
when al test have been successful (even those that were run before this invocation). Implements TestCase.
Invokes TestCase::runBare()
for each test in the collection.
TestSuite<TestCase>::reset()
before each test.TestCase::setUp()
before each test.TestCase::tearDown()
after each test. {{ // 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<TestCase> 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 ); }}
Reimplemented from TestCase.
template< class TestCase > int TestSuite< TestCase >::countTestCases | ( | ) | const [inline] |
int TestSuite< TestCase >::failureCount | ( | ) | const [virtual] |
int TestSuite< TestCase >::successCount | ( | ) | const [virtual] |
template< class TestCase > bool TestSuite< TestCase >::iAmTestSuite | ( | ) | const [inline, private, virtual] |
template< class TestCase > TestSuite< TestCase >::TestSuite & TestSuite< TestCase >::operator= | ( | const TestSuite< TestCase > & | DONTcopy | ) | [private] |
This "private"
declaration forbids test case copying.
bool TestCase::Run | ( | ) | [inline, inherited] |
bool TestCase::runTest | ( | ) | [inline, inherited] |
void TestCase::setUp | ( | ) | [inline, virtual, inherited] |
Sets the environment for the test run.
TestCase::run()
is an abstract method, to facilitate programming it is usual for the programmer not to invoke TestCase::setUp()
and TestCase::tearDown()
because it is easier to have TestSuite<TestCase>::runBare()
do it.TestCase::runBare()
, method TestCase::run()
will not establish the test environment because it does not invoke neither TestCase::setUp()
before the test run nor TestCase::tearDown()
after the test run.TestSuite<TestCase>::runBare()
invokes methods TestCase::setUp()
and TestCase::tearDown()
when the test run is executed.TestSuite
and execute all of them invoking TestSuite<TestCase>::runBare()
. Reimplemented in test_rational< INT >, ADH::test_Graph, and test1.
void TestCase::tearDown | ( | ) | [inline, virtual, inherited] |
int TestCase::runCount | ( | ) | const [inline, inherited] |
Number of test runs.
successCount()+failureCount()+errorCount()
. int TestCase::errorCount | ( | ) | const [inline, inherited] |
Always returns 0
(cero): "Number of errors".
bool TestCase::wasSuccessful | ( | ) | const [inline, inherited] |
Returns "true"
when all test runs where successful.
(successCount() == runCount())
std::string TestCase::getName | ( | ) | const [inline, inherited] |
void TestCase::setName | ( | const char * | name = 0 | ) | [inline, inherited] |
Sets the test case name to "name"
.
"name"
is a null string or pointer, later typeid(*this).name()
will be invoked to get the test´s name. {{ // 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 } }}
std::string TestCase::toString | ( | const T & | val | ) | [static, inherited] |
Returns a std::string
constructed form value val
.
toString()
with standard C++ const std::string TestCase::report | ( | ) | const [inline, inherited] |
Returns string summary()
followed by toString()
.
const std::string TestCase::failureString | ( | ) | const [inline, inherited] |
Synonym for toString()
.
void TestCase::recordSuccess | ( | ) | [inline, protected, inherited] |
void TestCase::recordFailure | ( | const char * | label, |
const char * | fname, | ||
int | lineno, | ||
bool | must_copy = false |
||
) | [inline, protected, inherited] |
Records that the test run did not succeed.
"fname"
and "lineno"
indicate the file and line where the test run is executed."fname"
and "lineno"
are usuallly obtained invoking global macros "__FILE__"
and "__LINE__"
."must_copy"
forces a copy of string label to be created in dynamic memory. This dynamic memory will be destroyed when the test case gets destroyed or when method TestCase::reset()
gets invoked."label"
is a constant string generated by the preprocessor macro using #cond
; this string constant is not stored in dynamic memory and it must not be destroyed.This method is invoked using macro BUnit_FAILURE()
.
void TestCase::recordFailure | ( | const std::string & | label, |
const char * | fname, | ||
int | lineno | ||
) | [inline, protected, inherited] |
void TestCase::testThis | ( | bool | cond, |
const char * | label, | ||
const char * | fname, | ||
long | lineno, | ||
bool | must_copy = false |
||
) | [inline, protected, inherited] |
Executes the test and records its result.
successCount()
.toString()
this fact."cond"
."fname"
and "lineno"
show the file and line of the executed test."fname"
and "lineno"
are values obtained with global macros "__FILE__"
and "__LINE__"
."must_copy"
indicates whether it is necessary to make a copy of string "label"
; this copy will be destroyed when the record of not successful test is deleted."label"
is a constant genertated by the preprocessor when using macro #cond
its memory must not be returned. This method is invoked using macro BUnit_TEST()
. {{ // 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() ); }}
void TestCase::testThis | ( | bool | cond, |
const std::string & | label, | ||
const char * | fname, | ||
long | lineno | ||
) | [inline, protected, inherited] |
Synonym for testThis()
.
int TestCase::nPass | ( | ) | const [inline, protected, inherited] |
int TestCase::nError | ( | ) | const [inline, protected, inherited] |
friend class TestSuite [friend, inherited] |
void do_toString | ( | const TestCase * | tc, |
std::basic_ostringstream< char > & | ost | ||
) | [friend, inherited] |
template< class TestCase > container_type TestSuite< TestCase >::m_allTest [private] |
int TestCase::m_pass [protected, inherited] |
int TestCase::m_failure [protected, inherited] |
const char * TestCase::m_name [protected, inherited] |
bool TestCase::m_test_suite_destroy [protected, inherited] |
std::list< TestCaseFailure > TestCase::m_failureList [protected, inherited] |