module unit_threaded.asserts; import std.conv; @safe: /** * Helper to call the standard assert */ void assertEqual(T, U)(T t, U u, string file = __FILE__, size_t line = __LINE__) @trusted /* std.conv.to */ { assert(t == u, "\n" ~ file ~ ":" ~ line.to!string ~ "\nExp: " ~ u.to!string ~ "\nGot: " ~ t.to!string); } void assertExceptionMsg(E)(lazy E expr, string expected, in string file = __FILE__, in size_t line = __LINE__) { import unit_threaded.should; import std.string: stripLeft, replace, split; import std.path: dirSeparator; import std.algorithm: map, all, endsWith; import std.range: zip; import std.conv: to; import core.exception; string getExceptionMsg(E)(lazy E expr) { try { expr(); } catch(UnitTestException ex) { return ex.toString; } assert(0, "Expression did not throw UnitTestException"); } //updating the tests below as line numbers change is tedious. //instead, replace the number there with the actual line number expected = expected.replace(":123", ":" ~ line.to!string).replace("/", dirSeparator); auto msg = getExceptionMsg(expr); auto expLines = expected.split("\n").map!stripLeft; auto msgLines = msg.split("\n").map!stripLeft; if(!zip(msgLines, expLines).all!(a => a[0].endsWith(a[1]))) { throw new AssertError(text("\nExpected Exception:\n", expected, "\nGot Exception:\n", msg), file, line); } }