namespace test {@test} load testing.base load meta import test.base const put = io.writef const AssertError = Error::define('Test::Assert') const AssertEqualError = Error::define('Test::AssertEqual') const AssertInRangeError = Error::define('Test::AssertInRange') const AssertNotInRangeError = Error::define('Test::AssertNotInRange') const AssertNotEqualError = Error::define('Test::AssertNotEqual') const AssertNoneError = Error::define('Test::AssertNone') const AssertNotNoneError = Error::define('Test::AssertNotNone') const AssertEmptyError = Error::define('Test::AssertEmpty') const AssertNotEmptyError = Error::define('Test::AssertNotEmpty') const AssertErrorError = Error::define('Test::AssertError') const SkipError = Error::define('Test::Skip') #! Marks routine as test and handles its execution. When not empty, *description* is used to describe the test, #! otherwise routine name is used in its stead routine @test(func(args): routine<>, description = ''){ invar caption = description == ''? meta.nameOf(func) : description; invar header = (string)base.newTest() + '. ' + caption + ' %s' invar err = std.try { func() } if (err == none){ put(header + '[green]\n', 'passed') base.testPassed() } else if (err ?< SkipError){ if (invar reason = ((SkipError)err).summary; reason != '') put(header + '[yellow] -- %s\n', 'skipped', reason) else put(header + '[yellow]\n', 'skipped') base.testSkipped() } else { invar fail = 'failed' invar line = err ?< Error? ((Error)err).line : ((list)err)[0].line invar hdr = header + '[red] -- line ' + (string)line + ': ' switch (err) type { case AssertError: put(hdr + '%s\n', fail, err.summary) case AssertEqualError: invar (actual, expected) = (tuple)err.data put(hdr + 'expected %a, found %a\n', fail, expected, actual) case AssertInRangeError: invar (actual, expected) = (tuple>)err.data put(hdr + 'expected [%a; %a], found %a\n', fail, expected[0], expected[1], actual) case AssertNotInRangeError: invar (actual, notExpected) = (tuple>)err.data put(hdr + 'expected not [%a; %a], found %a\n', fail, notExpected[0], notExpected[1], actual) case AssertNotEqualError: put(hdr + 'expected not %a\n', fail, err.data) case AssertNoneError: put(hdr + 'expected none, found %a\n', fail, err.data) case AssertNotNoneError: put(hdr + 'expected not none\n', fail) case AssertEmptyError: put(hdr + 'expected empty value, found %a\n', fail, err.data) case AssertNotEmptyError: put(hdr + 'expected non-empty value\n', fail) case AssertErrorError: put(hdr + '\n', fail) case Error: put(hdr + 'error: %s -- %s\n', fail, err.name, err.summary) case list: put(hdr + 'multiple errors', fail) } base.testFailed() } }