Check output in Bats
Capture a command's output and status in Bats with run, then assert on $output and $status. run keeps a failing command from ending the test early.
A test needs to check what a command printed, and to check that it failed in the right way.
cat > out.bats <<'EOF'
@test "output is checked as a whole string" {
run echo "hello world"
[ "$status" -eq 0 ]
[ "$output" = "hello world" ]
}
@test "output can be matched as a pattern" {
run printf 'one\ntwo\nthree\n'
[[ $output == *two* ]]
[ "${lines[1]}" = "two" ]
[ "${#lines[@]}" -eq 3 ]
}
@test "a failing command is captured, not fatal" {
run ls /nonexistent
[ "$status" -ne 0 ]
[[ $output == *"No such file"* ]]
}
@test "mismatch shows the failing line" {
run echo "hello"
[ "$output" = "bye" ]
}
EOF
bats out.bats1..4
ok 1 output is checked as a whole string
ok 2 output can be matched as a pattern
ok 3 a failing command is captured, not fatal
not ok 4 mismatch shows the failing line
# (in test file out.bats, line 22)
# `[ "$output" = "bye" ]' failedrun executes the command, stores its combined standard output and standard error in $output, its exit status in $status and the output split by lines in the $lines array, all described in the Bats guide to writing tests. Because run always returns 0 itself, a command that fails cannot end the test before you look at $status. The last test shows the report for a failed assertion: the file, the line and the command.
$output merges both streams, so the order of stdout and stderr lines can differ from the terminal. Use run --separate-stderr from Bats 1.5 to keep them apart. Do not call run on a shell function that changes variables, as it executes in a subshell and the changes are lost.