docs/traps.md: the trap of a bats negation that is not the last command #15
Labels
No labels
accessibility
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Keel-Linux/handbook#15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
docs/traps.mdis missing the trap found on 2026-09-28, and it is one of the cheapest to fall into again because the broken shape and the working shape are one word apart.The trap
A bats test body has no assertions of its own: its verdict is the exit status of the last command it ran. Bash does not apply errexit to a negated command — the exemption is in the shell by design, so a script can test a command without dying — so
! cmdon its own line decides the test when it is the final command of the body and is inert everywhere else. Moving a line, or appending one after it, silently changes whether it asserts.Measured over every default branch in the organization that carries a bats file (19 of them): 57 inert negations in 8 repositories, beside 45 in final position that do assert. The worst was
inithookstests/test-ipconfig.bats, where twelve of the thirteen rejection cases ofipconfig_ip6_syntaxwere inert — an IPv6 validator's rejection set, in an IPv6-first distribution, a few entries in this same file below the one about IPv6 literals.Two of the entries already in
docs/traps.mdhad a regression test written for them, and in both cases that test was inert:unit-redis's refutation that the bind fragment never sayslocalhost, and its refutation that noadminuser is declared at build time.What the entry needs
The shape the others use:
!decides anything. Including the shellcheck sweep and the fact that shellcheck grades the two cases apart,error:inert andnote:still asserting, which is what makes the sweep exact.run ! cmdwithbats_require_minimum_version 1.5.0, applied to every negation and not only the inert ones. Plus the two things that bite while converting:runreplaces$output/$status/$lines, so a body that refutes and then reads the output of what it was refuting has to keep it in a local first; andruntakes a command, not a pipeline.Negations that assert (SC2314)step oftest-shell.ymlin the.githubrepository, which every repository with a bats suite already calls at@main.It should also be honest that every predicate turned out to be correct, so nothing shipped broken, and that this is luck rather than evidence — with the one assertion that did fail when it was turned on named, because that one could never have passed for any input.
Related: Keel-Linux/tracker#19 and Keel-Linux/.github#13.