Skip to content

Global state creates unpredictable zig test results #11080

Open
@danielchasehooper

Description

@danielchasehooper

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:

  1. Working on one test can cause seemingly unrelated tests to change pass/fail
  2. Reordering tests can change which tests pass/fail
  3. Filtering tests with --test-filter flag can change which tests pass/fail
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions