Testing
Asserts
fn foo(mut v []int) {
v[0] = 1
}
mut v := [20]
foo(mut v)
assert v[0] < 4
An assert
statement checks that its expression evaluates to true
. If an assert fails,
the program will abort. Asserts should only be used to detect programming errors. When an
assert fails it is reported to stderr, and the values on each side of a comparison operator
(such as <
, ==
) will be printed when possible. This is useful to easily find an
unexpected value. Assert statements can be used in any function.
Test files
// hello.v
module main
fn hello() string {
return 'Hello world'
}
fn main() {
println(hello())
}
// failcompile
// hello_test.v
module main
fn test_hello() {
assert hello() == 'Hello world'
}
To run the test above, use v hello_test.v
. This will check that the function hello
is
producing the correct output. V executes all test functions in the file.
- All test functions have to be inside a test file whose name ends in
_test.v
. - Test function names must begin with
test_
to mark them for execution. - Normal functions can also be defined in test files, and should be called manually. Other symbols can also be defined in test files e.g. types.
- There are two kinds of tests: external and internal.
- Internal tests must declare their module, just like all other .v files from the same module. Internal tests can even call private functions in the same module.
- External tests must import the modules which they test. They do not have access to the private functions/types of the modules. They can test only the external/public API that a module provides.
In the example above, test_hello
is an internal test, that can call
the private function hello()
because hello_test.v
has module main
,
just like hello.v
, i.e. both are part of the same module. Note also that
since module main
is a regular module like the others, internal tests can
be used to test private functions in your main program .v files too.
You can also define these special test functions in a test file:
testsuite_begin
which will be run before all other test functions.testsuite_end
which will be run after all other test functions.
If a test function has an error return type, any propagated errors will fail the test:
import strconv
fn test_atoi() ? {
assert strconv.atoi('1')? == 1
assert strconv.atoi('one')? == 1 // test will fail
}
Running tests
To run test functions in an individual test file, use v foo_test.v
.
To test an entire module, use v test mymodule
. You can also use v test .
to test
everything inside your current folder (and subfolders). You can pass the -stats
option to see more details about the individual tests run.
You can put additional test data, including .v source files in a folder, named
testdata
, right next to your _test.v files. V’s test framework will ignore
such folders, while scanning for tests to run. This is useful, if you want to
put .v files with invalid V source code, or other tests, including known
failing ones, that should be run in a specific way/options by a parent _test.v
file.
NB: the path to the V compiler, is available through @VEXE, so a _test.v file, can easily run other test files like this:
// oksyntax
import os
fn test_subtest() {
res := os.execute('${os.quoted_path(@VEXE)} other_test.v')
assert res.exit_code == 1
assert res.output.contains('other_test.v does not exist')
}