Skip to content
shellhacks.dev
Testing

Check status in Bats

Check a command's exit code in Bats with run and $status. run never fails the test by itself, and Bats 1.5 added run -N to assert the status in one line.

2 min read
Summarize in AI

A Bats test needs to check that a command fails with a particular status, and a failing command normally stops the test.

Shell
cat > status.bats <<'EOT'
bats_require_minimum_version 1.5.0

@test "capture the status and output" {
  run bash -c 'echo out; echo err >&2; exit 3'
  [ "$status" -eq 3 ]
  [ "$output" = $'out\nerr' ]
}

@test "assert the status on the run line" {
  run -3 bash -c 'exit 3'
}

@test "run alone checks nothing" {
  run false
}

@test "a wrong status fails" {
  run false
  [ "$status" -eq 0 ]
}
EOT
bats status.bats
echo "bats exit: $?"
Text
1..4
ok 1 capture the status and output
ok 2 assert the status on the run line
ok 3 run alone checks nothing
not ok 4 a wrong status fails
# (in test file status.bats, line 19)
#   `[ "$status" -eq 0 ]' failed
bats exit: 1

run executes the command, stores its exit code in $status and its combined standard output and error in $output, and always succeeds itself, so the test goes on to your own checks. The third test passes while testing nothing, because false is run and nobody looks at the result. With Bats 1.5 or later run -3 also asserts that the status is 3, and run ! asserts any non-zero status. Both are in the Bats documentation.

run starts the command in a subshell, so a variable it sets is lost and cd does not stick. A pipe is not part of the command: run a | b runs b on the output of run, so use run bash -c 'a | b'. Without bats_require_minimum_version 1.5.0 the -N form prints a warning. The dollar-quoted string in the first test needs Bash.

Share

More snippets

Testing

Choose the shell for ShellCheck

Tell ShellCheck which shell a script targets with -s bash or -s sh. Without a shebang it cannot tell, and as sh it flags every Bash-only feature as SC3xxx.

2 min read
Testing

Skip a Bats test

Skip a Bats test with skip or skip "reason", which can be called in the middle of a test. A skipped test counts as passed, and the reason shows in the output.

2 min read
Testing

Load helpers in Bats

Share code between Bats tests with load helpers, which reads helpers.bash from the test file's directory. A plain source breaks when bats runs from elsewhere.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.