@@ -1,49 +1,58 @@ /** * Authors: k.inaba * License: NYSL 0.9982 http://www.kmonos.net/nysl/ * - * Unittest helpers. - * TODO: use stderr instead of stdout. the problem is that std.cstream is xxxx.... - * TODO: is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? + * Hepler routines for unittesting. + * TODO: Is there any clean way to implement "assert_compiles" and "assert_not_compile"? */ module tricks.test; -import std.conv : to; +import std.conv : text; import core.exception; version(unittest) { - import std.stdio; + import std.cstream; import core.runtime; - // Install custom test runner static this() { + installCustomTestRunner(); + } + + private void installCustomTestRunner() + { Runtime.moduleUnitTester = function() { - Throwable ee = null; - size_t failed=0; - foreach(m; ModuleInfo) if(m) if(auto fp=m.unitTest) + Throwable firstError = null; + + void logError(Throwable e) + { + if(firstError is null) + firstError = e; + derr.writefln(" !! %s(%d): %s", e.file, e.line, e.msg); + } + + void testModule(ModuleInfo* m, void function() test) { - writeln("[TEST] ", m.name); - try { - fp(); - } catch( Throwable e ) { - if(ee is null) - ee = e; - failed++; - writeln(" !! ",e.file,"(",e.line,"): ",e.msg); - } + derr.writefln("[TEST] %s", m.name); + try { test(); } catch( Throwable e ) { logError(e); } } - if(ee !is null) + + bool report() { - writeln("[TEST] ",failed," modules failed. The first error was:"); - writeln(ee); - write("[TEST] press enter to exit."); - readln(); + if(firstError is null) + return true; + derr.writefln("[TEST] The first error was:\n%s", firstError); + derr.writeString("[TEST] press enter to exit."); + din.readLine(); return false; } - return true; + + foreach(m; ModuleInfo) + if(m && m.unitTest) + testModule(m, m.unitTest); + return report(); }; } } @@ -100,9 +109,9 @@ try { if( mixin("a"~op~"b") ) return; } catch(Throwable e) { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n >> "~e.toString()); } - onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~" "~to!string(b)); + onAssertErrorMsg(fn, ln, msg.length ? msg : text(a, " !", op, " ", b)); } } alias assertOp!(`==`) assert_eq; /// asserts two operands are ==