Testsuite: catch exceptions at the level of invoking individual tests
This commit is contained in:
parent
cb7c884293
commit
3835399c5f
4 changed files with 76 additions and 30 deletions
|
|
@ -48,7 +48,7 @@ namespace lumiera {
|
|||
inline void
|
||||
log_and_clear_unexpected_errorstate ()
|
||||
{
|
||||
if (const char * errorstate = lumiera_error ())
|
||||
if (lumiera_err errorstate = lumiera_error ())
|
||||
ALERT (common, "*** Unexpected error: %s\n Triggering emergency exit.", errorstate);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,17 @@
|
|||
|
||||
*/
|
||||
|
||||
/** @file run.hpp
|
||||
** Simple test class runner. Allows for writing unit tests as subclass of
|
||||
** test::Test . They may be installed for automatic invocation through test::Suite
|
||||
** by defining a Launcher instance, which can be done conveniently by the macro LAUNCHER
|
||||
**
|
||||
** @see HelloWorld_test
|
||||
** @see test::Suite
|
||||
** @see mainsuite.cpp
|
||||
** @see main.cpp
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TESTHELPER_RUN_H
|
||||
#define TESTHELPER_RUN_H
|
||||
|
|
@ -37,12 +48,11 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
namespace test {
|
||||
|
||||
using std::string;
|
||||
using std::auto_ptr;
|
||||
|
||||
|
||||
typedef std::vector<string> & Arg;
|
||||
|
||||
|
||||
|
|
@ -60,7 +70,7 @@ namespace test
|
|||
|
||||
|
||||
|
||||
/** interface: generic testcase creating functor. */
|
||||
/** interface: generic testcase creating functor. */
|
||||
class Launcher
|
||||
{
|
||||
public:
|
||||
|
|
@ -86,7 +96,7 @@ namespace test
|
|||
public:
|
||||
Launch (string testID, string groups) { Suite::enrol (this,testID,groups); };
|
||||
virtual auto_ptr<Test> operator() () { return auto_ptr<Test> (new TEST ); };
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
|
|
|
|||
|
|
@ -22,26 +22,29 @@
|
|||
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <tr1/memory>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "include/logging.h"
|
||||
#include "lib/cmdline.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/test/suite.hpp"
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <tr1/memory>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace test {
|
||||
|
||||
using std::map;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
using std::auto_ptr;
|
||||
using std::tr1::shared_ptr;
|
||||
|
|
@ -49,6 +52,7 @@ namespace test {
|
|||
|
||||
using util::isnil;
|
||||
using util::contains;
|
||||
using lib::test::showType;
|
||||
|
||||
typedef map<string, Launcher*> TestMap;
|
||||
typedef shared_ptr<TestMap> PTestMap;
|
||||
|
|
@ -133,14 +137,30 @@ namespace test {
|
|||
TRACE(test, "Test-Suite( groupID=%s )\n", groupID.c_str () );
|
||||
|
||||
if (!testcases.getGroup(groupID))
|
||||
throw lumiera::error::Invalid ();
|
||||
//throw "empty testsuite"; /////////// TODO Errorhandling!
|
||||
throw lumiera::error::Invalid ("empty testsuite");
|
||||
}
|
||||
|
||||
#define VALID(test,testID) \
|
||||
ASSERT ((test), "NULL testcase launcher for test '%s' found in testsuite '%s'", groupID_.c_str(),testID.c_str());
|
||||
|
||||
|
||||
namespace { // internal helper for launching with error logging
|
||||
|
||||
void
|
||||
invokeTestCase (Test& theTest, Arg cmdline)
|
||||
{
|
||||
try { theTest.run (cmdline); }
|
||||
catch (lumiera::Error& failure)
|
||||
{
|
||||
lumiera_err errorID = lumiera_error(); // reset error flag
|
||||
cerr << "*** Test Failure " << showType(theTest) << endl;
|
||||
cerr << "*** : " << failure.what() << endl;
|
||||
ERROR (test, "Error state %s", errorID);
|
||||
WARN (progress, "Caught exception %s", failure.what());
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
/** run all testcases contained in this Suite.
|
||||
* The first argument in the commandline, if present,
|
||||
* will select one single testcase with a matching ID.
|
||||
|
|
@ -155,7 +175,7 @@ namespace test {
|
|||
{
|
||||
PTestMap tests = testcases.getGroup(groupID_);
|
||||
if (!tests)
|
||||
throw lumiera::error::Invalid (); ///////// TODO: pass error description
|
||||
throw lumiera::error::Invalid ("test group not found"); ///////// TODO: pass error description
|
||||
|
||||
if (0 < cmdline.size())
|
||||
{
|
||||
|
|
@ -168,7 +188,7 @@ namespace test {
|
|||
Launcher* test = (*tests)[testID];
|
||||
cmdline.erase (cmdline.begin());
|
||||
VALID (test,testID);
|
||||
(*test)()->run(cmdline);
|
||||
invokeTestCase (*(*test)(), cmdline); // TODO confusing statement, improve definition of test collection datatype Ticket #289
|
||||
return;
|
||||
} }
|
||||
|
||||
|
|
@ -179,7 +199,7 @@ namespace test {
|
|||
std::cout << "\n ----------"<< i->first<< "----------\n";
|
||||
Launcher* test = (i->second);
|
||||
VALID (test, i->first);
|
||||
(*test)()->run(cmdline); // actually no cmdline arguments
|
||||
invokeTestCase (*(*test)(), cmdline); // actually no cmdline arguments
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -194,13 +214,13 @@ namespace test {
|
|||
PTestMap tests = testcases.getGroup(groupID_);
|
||||
ASSERT (tests);
|
||||
|
||||
std::cout << "TESTING \"Component Test Suite: " << groupID_ << "\" ./test-components\n\n";
|
||||
cout << "TESTING \"Component Test Suite: " << groupID_ << "\" ./test-components\n\n";
|
||||
|
||||
for ( TestMap::iterator i=tests->begin(); i!=tests->end(); ++i )
|
||||
{
|
||||
string key (i->first);
|
||||
std::cout << "\n\n";
|
||||
std::cout << "TEST \""<<key<<"\" "<<key<<" <<END\n";
|
||||
cout << "\n\n";
|
||||
cout << "TEST \""<<key<<"\" "<<key<<" <<END\n";
|
||||
Launcher* test = (i->second);
|
||||
VALID (test, i->first);
|
||||
try
|
||||
|
|
@ -209,9 +229,9 @@ namespace test {
|
|||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "PLANNED ============= " << lumiera_error() << "\n";
|
||||
cout << "PLANNED ============= " << lumiera_error() << "\n";
|
||||
}
|
||||
std::cout << "END\n";
|
||||
cout << "END\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,22 @@
|
|||
|
||||
*/
|
||||
|
||||
/** @file suite.hpp
|
||||
** Building and running a suite of tests, implemented as test classes.
|
||||
** This simple test suite runner is intended to be linked into a standalone C++ application,
|
||||
** allowing to invoke individual tests by ID, invoking groups of tests and producing a
|
||||
** report of all registered tests. Registration of individual testcases happens
|
||||
** automatically through static test::Launcher instances.
|
||||
**
|
||||
** @todo as of 9/09, the implementation seems OKish but a bit clumsy. See Ticket #289
|
||||
**
|
||||
** @see HelloWorld_test
|
||||
** @see test::Test
|
||||
** @see test::TestOption
|
||||
** @see run.hpp
|
||||
** @see mainsuite.cpp
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TESTHELPER_SUITE_H
|
||||
#define TESTHELPER_SUITE_H
|
||||
|
|
@ -29,21 +45,21 @@
|
|||
|
||||
|
||||
|
||||
namespace test
|
||||
{
|
||||
namespace test {
|
||||
|
||||
using std::string;
|
||||
|
||||
// Forward decls needed for run.hpp
|
||||
// Forward declarations for run.hpp
|
||||
class Test;
|
||||
class Launcher;
|
||||
|
||||
|
||||
typedef std::vector<string> & Arg;
|
||||
|
||||
|
||||
/**
|
||||
* Enables running a collection of tests.
|
||||
* An internal registration service #enrol() is provided
|
||||
* for the individual Test - inscances to be recognized as
|
||||
* for the individual Test - instances to be recognised as
|
||||
* testcases. The groupID passed to the constructor selects
|
||||
* all testcases declared as belonging to this Group.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue