Description
Zig Version
0.10.0-dev.871+bb05a8a08
Steps to Reproduce
Imagine you saw the following output:
$ zig test globalteststate.zig --test-filter "buzz"
TestAll 1 tests passed.
$ zig test globalteststate.zig --test-filter "fizz"
TestAll 1 tests passed.
$ zig test globalteststate.zig
TestTestTest [2/2] test "buzz"... FAIL (TestUnexpectedResult)
That would be very surprising! The two tests pass on their own, but when both tests are run together, a test fails.
You can recreate the above situation with the following contents of globalteststate.zig
var global_state_clean = true;
test "fizz" {
global_state_clean = false;
}
test "buzz" {
try @import("std").testing.expect(global_state_clean);
}
This is a trivial example that exemplifies a situation that can manifest in much less obvious ways in large projects.
Expected Behavior
I'd expect each test to be run with a "clean" global state untarnished by other tests.
Actual Behavior
Tests can affect the results of other tests. this can lead to very confusing situations.
Notes
These situations can be triggered in several ways that are very common in practice:
- Working on one test can cause seemingly unrelated tests to change pass/fail
- Reordering tests can change which tests pass/fail
- Filtering tests with
--test-filter
flag can change which tests pass/fail - Running tests on more resource constrained systems can cause later tests to fail due to earlier tests using up system resources. I think this would be especially confusing since the state is in the OS and not in your code.
In effect you're testing global behaviors / orderings without explicitly intending to do that.
I hope everyone can see why this is a problem and don't write it off as "if you have global state, that's on you". Global state is common, even in non-obvious ways like open file handles, process memory use, etc. If tests act in unpredictable ways, it'll make people less likely to use them and/or trust them less. Off the top of my head, it'd be nice if after the test process had set up global state, but before any tests are run, it would fork() for each test so they're run in an untarnished process - but I leave it up to the Zig committee to decide how best to handle this.