v/vlib/v/preludes/test_runner.v

126 lines
4.1 KiB
V

[has_globals]
module main
__global test_runner TestRunner
///////////////////////////////////////////////////////////////////////////////
// This file will be compiled as part of the main program, for a _test.v file.
// The methods defined here are called back by the test program's assert
// statements, on each success/fail. The goal is to make customizing the look &
// feel of the assertions results easier, since it is done in normal V code.
///////////////////////////////////////////////////////////////////////////////
interface TestRunner {
mut:
file_test_info VTestFileMetaInfo // filled in by generated code, before .start() is called.
fn_test_info VTestFnMetaInfo // filled in by generated code, before .fn_start() is called.
fn_assert_passes u64 // reset this to 0 in .fn_start(), increase it in .assert_pass()
fn_passes u64 // increase this in .fn_pass()
fn_fails u64 // increase this in .fn_fails()
total_assert_passes u64 // increase this in .assert_pass()
total_assert_fails u64 // increase this in .assert_fail()
start(ntests int) // called before all tests, you can initialise private data here. ntests is the number of test functions in the _test.v file.
finish() // called after all tests are finished, you can print some stats if you want here.
exit_code() int // called right after finish(), it should return the exit code, that the test program will exit with.
//
fn_start() bool // called before the start of each test_ function. Return false, if the function should be skipped.
fn_pass() // called after the end of each test_ function, with NO failed assertion.
fn_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error.
fn_error(line_nr int, file string, mod string, fn_name string, errmsg string) // called only for `fn test_xyz() ? { return error('message') }`, before .fn_fail() is called.
//
assert_pass(i &VAssertMetaInfo) // called after each `assert true`.
assert_fail(i &VAssertMetaInfo) // called after each `assert false`.
//
free() // you should free all the private data of your runner here.
}
//
struct VTestFileMetaInfo {
file string
tests int
}
// vtest_new_filemetainfo will be called right before .start(ntests),
// to fill in the .file_test_info field of the runner interface.
fn vtest_new_filemetainfo(file string, tests int) VTestFileMetaInfo {
return VTestFileMetaInfo{
file: file
tests: tests
}
}
[unsafe]
fn (i &VTestFileMetaInfo) free() {
unsafe {
i.file.free()
}
}
//
struct VTestFnMetaInfo {
name string
mod string
file string
line_nr int
}
// vtest_new_metainfo will be called once per each test function.
fn vtest_new_metainfo(name string, mod string, file string, line_nr int) VTestFnMetaInfo {
return VTestFnMetaInfo{
name: name
mod: mod
file: file
line_nr: line_nr
}
}
[unsafe]
fn (i &VTestFnMetaInfo) free() {
unsafe {
i.name.free()
i.mod.free()
i.file.free()
}
}
//
[typedef]
struct C.main__TestRunner {
mut:
_object voidptr
}
// change_test_runner should be called by preludes that implement the
// the TestRunner interface, in their vtest_init fn (see below), to
// customize the way that V shows test results
[manualfree]
pub fn change_test_runner(x &TestRunner) {
pobj := unsafe { &C.main__TestRunner(&test_runner)._object }
if pobj != 0 {
test_runner.free()
unsafe {
(&C.main__TestRunner(&test_runner))._object = voidptr(0)
}
}
test_runner = *x
}
// vtest_init will be caled *before* the normal _vinit() function,
// to give a chance to the test runner implemenation to change the
// test_runner global variable. The reason vtest_init is called before
// _vinit, is because a _test.v file can define consts, and they in turn
// may use function calls in their declaration, which may do assertions.
// fn vtest_init() {
// change_test_runner(&TestRunner(AnotherTestRunner{}))
// }
// TODO: remove vtest_option_cludge, it is only here so that
// `vlib/sync/channel_close_test.v` compiles with simpler runners,
// that do not `import os` (which has other `fn()?`). Without it,
// the C `Option_void` type is undefined -> C compilation error.
fn vtest_option_cludge() ? {
}