You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Under --parallel the runner dispatches a file's tests as a background worker, then runs tear_down_after_script in the parent on the very next line. The hook releases the file's resources while the tests that need them are still running.
Same class as #1318: a file-scoped hook that does not line up with the work it is supposed to wrap. There the hook never ran. Here it runs too early.
The same file passes under --no-parallel and fails under --parallel, which is exactly the sequential/parallel divergence #1150 set out to stop.
Current behavior
tear_down_after_script runs immediately after the fork, before the worker has executed a single test. Tests that read a resource created in set_up_before_script fail against whatever the hook left behind. The failure is reported against the test, so nothing points at the hook.
$ CLEANUP_MARKER=/tmp/bu-race.marker ./bashunit --no-parallel race_test.sh
Tests: 1 passed, 1 total
Parallel fails:
$ CLEANUP_MARKER=/tmp/bu-race.marker ./bashunit --parallel race_test.sh
✗ Failed: Needs resource
Expected '/tmp/bu-race.marker'
to exist but 'do not exist'
Tests: 1 failed, 1 total
Expected behavior
tear_down_after_script runs after the file's tests have finished, in both modes. A file that passes sequentially passes in parallel.
Where it happens
src/runner/discovery.sh:
line 231: bashunit::runner::call_test_functions "$test_file" "$_cached_fns" 2>"$_worker_stderr" &
line 235: bashunit::runner::run_tear_down_after_script "$test_file" runs in the parent
line 249: wait runs only after the whole file loop
Acceptance criteria
An acceptance test with a file whose test sleeps, then asserts a resource created in set_up_before_script. It passes under --no-parallel and --parallel.
A tear_down_after_script that fails is still counted, and still reported against the hook, under --parallel.
./bashunit tests/ and ./bashunit --parallel tests/ green.
The caveat at docs/ai-agents.md:144 ("Do not delete a shared fixture in tear_down_after_script") is removed or rewritten, since it exists only to work around this.
CHANGELOG.md gets a Fixed entry.
Notes for the implementer
Moving the hook into call_test_functions is the obvious shape, but that runs in a subshell. State written there dies with it, which is the trap Duplicate test functions go undetected under --parallel #1147 documents and the comment at discovery.sh:216 restates. A hook failure has to reach the parent through the result payload, the same channel the worker already uses for test results.
Waiting on the file's own worker before running the hook is correct and simple, and it serialises the run one file at a time. Measure the suite before choosing it.
set_up_before_script runs in the parent before the fork, so the worker inherits its state. Only the teardown side is misplaced.
Bash 3.0+ only. See .claude/rules/bash-style.md.
make sa, make lint, ./bashunit tests/, ./bashunit --parallel tests/.
Summary
Under
--parallelthe runner dispatches a file's tests as a background worker, then runstear_down_after_scriptin the parent on the very next line. The hook releases the file's resources while the tests that need them are still running.Same class as #1318: a file-scoped hook that does not line up with the work it is supposed to wrap. There the hook never ran. Here it runs too early.
The same file passes under
--no-paralleland fails under--parallel, which is exactly the sequential/parallel divergence #1150 set out to stop.Current behavior
tear_down_after_scriptruns immediately after the fork, before the worker has executed a single test. Tests that read a resource created inset_up_before_scriptfail against whatever the hook left behind. The failure is reported against the test, so nothing points at the hook.How to reproduce
race_test.sh:Sequential passes:
Parallel fails:
Expected behavior
tear_down_after_scriptruns after the file's tests have finished, in both modes. A file that passes sequentially passes in parallel.Where it happens
src/runner/discovery.sh:bashunit::runner::call_test_functions "$test_file" "$_cached_fns" 2>"$_worker_stderr" &bashunit::runner::run_tear_down_after_script "$test_file"runs in the parentwaitruns only after the whole file loopAcceptance criteria
set_up_before_script. It passes under--no-paralleland--parallel.tear_down_after_scriptthat fails is still counted, and still reported against the hook, under--parallel../bashunit tests/and./bashunit --parallel tests/green.docs/ai-agents.md:144("Do not delete a shared fixture intear_down_after_script") is removed or rewritten, since it exists only to work around this.CHANGELOG.mdgets aFixedentry.Notes for the implementer
call_test_functionsis the obvious shape, but that runs in a subshell. State written there dies with it, which is the trap Duplicate test functions go undetected under --parallel #1147 documents and the comment atdiscovery.sh:216restates. A hook failure has to reach the parent through the result payload, the same channel the worker already uses for test results.set_up_before_scriptruns in the parent before the fork, so the worker inherits its state. Only the teardown side is misplaced..claude/rules/bash-style.md.make sa,make lint,./bashunit tests/,./bashunit --parallel tests/.