/////////////////////////////////////////////////////////////////// // Test.cpp - implements the Test class, which supports // // ver 2.0 definition of a single test // // // // Language: Visual C++, ver 6.0, SP 4 // // Platform: Dell XPS1000, Windows 2000 Professional, SP 1 // // Author: Jim Fawcett, CST 2-187, Syracuse University // // jfawcett@twcny.rr.com, 315-443-3948 // // Source: // // The origianl design and implementation are by Chuck // // Allison (see ref, below), but I have modified his code // // and so take responsibility for this product. // /////////////////////////////////////////////////////////////////// // Notes: // // - This is a demonstration of a test harness that provides // // semi-automated low-level testing. // // - Goal is to run a suite of tests that return pass/fail // // information. // // - The intent is that you will use the test harness after // // every modification to your code, getting quick evidence // // that the change did or did not break anything. // // // // - To use the harness you have to implement simple test // // classes, derived from class Test, provided by this module. // // - You then declare an instance of class Suite, provided // // by the harness and add an instance of each test class. // // The test harness: // // - sequences through all your tests, // // - keeps records of passes and failures // // - handles display of the results // // // // Reference: // // The Simplest Automated Unit Test Framework That Could // // Possibly Work, Chuck Allison, C/C++ Users Journal, // // September 2000 // /////////////////////////////////////////////////////////////////// // #include "test.h" #include #include // Visual Studio requires /GR"" using namespace std; //----< run test, record results >------------------------------- void Test::do_test(bool cond, const std::string& lbl, const char* fname, long lineno) { if (!cond) do_fail(lbl, fname, lineno); else _succeed(); } //----< increment failure stats, announce failure >-------------- // // If m_osptr points to an ostringstream, announcement // will be saved for later delivery. If it is an ostream // it will be sent immediately. void Test::do_fail(const std::string& lbl, const char* fname, long lineno) { ++m_nFail; if (m_osptr) { *m_osptr << "\n " << typeid(*this).name() << "\n failure: (" << lbl << ")" << "\n File: " << fname << "\n Line: " << lineno << "\n"; } } //----< report test statistics >--------------------------------- long Test::report() const { if (m_osptr) { *m_osptr << "\n Test \"" << typeid(*this).name() << "\":\n" << "\tPassed: " << m_nPass << "\tFailed: " << m_nFail; } return m_nFail; } // //----< test classes >------------------------------------------- #ifdef TEST_TEST class myTest1 : public Test { public: myTest1(ostream *osptr) : Test(osptr) { } void run() { _test(true); _test(false); } }; class myTest2 : public Test { public: myTest2(ostream *osptr) : Test(osptr) { } void run() { _test(3==3); _test(3==5); } }; //----< test entry point >--------------------------------------- void main() { cout << "\n Testing Test Class " << "\n ====================\n"; myTest1 test1(&cout); test1.run(); cout << "\n passed: " << test1.getNumPassed() << "\n failed: " << test1.getNumFailed() << endl; test1.report(); myTest2 test2(&cout); test2.run(); test2.report(); cout << "\n\n"; } #endif