Testing and Benchmarking

38.1 Unit Tests

Assertion failures print the expression and its values. Tests can live in the module (internal) or in a separate tests/ directory (external, using import).

// calc.v
module calc
pub fn add(a int, b int) int { return a + b }
pub fn divide(a int, b int) !int {
	if b == 0 { return error('division by zero') }
	return a / b
}
// calc_test.v
module calc

fn testsuite_begin() { println('setup once') }
fn testsuite_end() { println('teardown once') }

fn test_add() {
	assert add(2, 3) == 5
	assert add(-1, 1) == 0, 'negatives should work'
}

fn test_divide_error() {
	divide(1, 0) or {
		assert err.msg() == 'division by zero'
		return
	}
	assert false, 'expected an error'
}

fn test_returning_result() ! {      // test fns may return results; errors fail the test
	assert divide(10, 2)! == 5
}
v test .                     # all *_test.v files recursively
v test calc_test.v
v -stats test .              # detailed stats
v -cov ./cov test .          # coverage (newer versions)
v test-all / v test-self     # compiler-level suites

38.2 Benchmarks

Compare builds: v -prod, -cc gcc vs clang, -autofree. Use hyperfine for CLI benchmarking.

import benchmark
mut b := benchmark.start()
for _ in 0 .. 1_000_000 { _ = fib(20) }
b.measure('fib(20) x 1M')

import time
sw := time.new_stopwatch()
// work
println('took ${sw.elapsed().milliseconds()}ms')