1 module unit_threaded.testcase; 2 3 import unit_threaded.check; 4 import unit_threaded.io; 5 6 import std.exception; 7 import std.string; 8 import std.conv; 9 10 struct TestResult { 11 immutable bool failed; 12 immutable string output; 13 } 14 15 /** 16 * Class from which other test cases derive 17 */ 18 class TestCase { 19 string getPath() const pure nothrow { 20 return this.classinfo.name; 21 } 22 23 final auto opCall() { 24 print(getPath() ~ ":\n"); 25 check(setup()); 26 check(test()); 27 check(shutdown()); 28 if(_failed) print("\n\n"); 29 return TestResult(_failed, _output); 30 } 31 32 void setup() { } ///override to run before test() 33 void shutdown() { } ///override to run after test() 34 abstract void test(); 35 36 private: 37 bool _failed; 38 string _output; 39 40 bool check(T = Exception, E)(lazy E expression) { 41 setStatus(collectExceptionMsg!T(expression)); 42 return !_failed; 43 } 44 45 void setStatus(in string msg) { 46 if(msg) { 47 _failed = true; 48 print(chomp(msg)); 49 } 50 } 51 52 void print(in string msg) { 53 addToOutput(_output, msg); 54 } 55 }