module unit_threaded.testcase; import unit_threaded.check; import unit_threaded.io; import std.exception; import std.string; import std.conv; struct TestResult { immutable bool failed; immutable string output; } /** * Class from which other test cases derive */ class TestCase { string getPath() const pure nothrow { return this.classinfo.name; } final auto opCall() { check(setup()); check(test()); check(shutdown()); if(_failed) addToOutput(_output, "\n\n"); return TestResult(_failed, _output); } void setup() { } ///override to run before test() void shutdown() { } ///override to run after test() abstract void test(); private: bool _failed; string _output; bool check(T = Exception, E)(lazy E expression) { setStatus(collectExceptionMsg!T(expression)); return !_failed; } void setStatus(in string msg) { if(msg) { _failed = true; addToOutput(_output, chomp(msg)); } } }