BATS(1)

πŸ’… BATS(1) β€” Bash Automated Testing System, but make it a vibe

okay bestie, welcome to bats β€” the Bash Automated Testing System, and yes, that's the whole manual name up top, I folded it in for you πŸŽ€ we are so back.


✨ NAME ✨

bats β€” Bash Automated Testing System. she's a testing framework, she's iconic, periodt. πŸ‘‘


✨ SYNOPSIS ✨

Usage: bats [OPTIONS] tests bats [-h | -v]

so tests (lowercase, the placeholder, don't come for me) is literally the path to a Bats test file, or the path to a directory containing Bats test files β€” and those files end with ".bats", no cap. πŸ“


✨ DESCRIPTION ✨

Bats is a TAP-compliant testing framework for Bash. It gives you a simple way to verify that the UNIX programs you write actually behave the way you expected, which β€” honestly β€” is the bare minimum and yet here we are. 🫢

A Bats test file is just a Bash script with special syntax for defining test cases. Under the hood, each test case is literally just a function with a description. that's it. that's the whole trick. ✨

Test cases are made of standard shell commands. Bats uses Bash's errexit (set -e) option when it runs test cases, so if every command in the test case exits with a status code of 0 (success), the test passes. which means every single line is basically an assertion of truth β€” main character energy for each line, honestly. πŸ’…

πŸ’‘ Wanna actually learn how to write these bad boys? Go read bats(7). she'll tell you everything.

🌈 RUNNING TESTS 🌈

To run your tests, invoke the bats interpreter with a path to a test file. The file's test cases run sequentially and in isolation (yes, isolated, they don't gossip with each other πŸ™ˆ). If all the test cases pass, bats exits with a 0 status code. If there are any failures, bats exits with a 1 status code. 😭

You can also invoke the bats interpreter with multiple test file arguments, or with a path to a directory containing multiple .bats files. Bats runs each test file individually and aggregates the results. If any test case fails, bats exits with a 1 status code β€” one bad apple and the whole exit status is in its flop era. πŸ“


πŸ¦‹ FILTERING TESTS πŸ¦‹

There are multiple mechanisms to filter which tests to execute, and they are lowkey giving choose-your-own-adventure:

  • --filter <regex> β€” filter by test name
  • --filter-status <status> β€” filter by the test's status in the last run
  • --filter-tags <tag-list> β€” filter by the tags of a test

🏷️ --FILTER-TAGS <tag-list>

Tags are for finegrained filtering of which tests to run, via --filter-tags. This accepts a comma separated list of tags, and only tests that match all of these tags get executed. For example, bats --filter-tags a,b,c will pick up tests with tags a,b,c, but not tests that miss one or more of those tags. picky queen πŸ’…

Bonus: you can specify negative tags via bats --filter-tags a,!b,c, which now won't match tests with tags a,b,c (because of the b, yeah), but will select a,c. To put it more formally, --filter-tags is a boolean conjunction. big words, slay. 🧠

To allow for more complex queries, you can specify multiple --filter-tags. A test will be executed if it matches at least one of them. This means multiple --filter-tags form a boolean disjunction. yes, the girlies are doing boolean logic now. πŸ”₯

A query of --filter-tags a,!b --filter-tags b,c can be translated to: Execute only tests that (have tag a, but not tag b) or (have tag b and c).

An empty tag list matches tests without tags. ⭐


πŸŽ€ OPTIONS πŸŽ€

  • --abort β€” Stop execution of suite on first failed test. like, we're done here, bye πŸ’€
  • --allow-empty-suite β€” Exit with code 0 (instead of the default code 1) when no tests are found.
  • -c, --count β€” Count the number of test cases without running any tests
  • --code-quote-style <style> β€” A two character string of code quote delimiters, or custom which requires setting $BATS_BEGIN_CODE_QUOTE and $BATS_END_CODE_QUOTE. Can also be set via $BATS_CODE_QUOTE_STYLE.
  • --line-reference-format β€” Controls how file/line references e.g. in stack traces are printed:
    • comma_line (default): a.bats, line 1
    • colon: a.bats:1
    • uri: file:///tests/a.bats:1
    • custom: provide your own via defining bats_format_file_line_reference_custom with parameters filename line, store via printf -v "$output"
  • --errexit β€” Enable errexit (set -e) for commands run in run
  • -f, --filter <regex> β€” Filter test cases by names matching the regular expression
  • -F, --formatter <type> β€” Switch between formatters: pretty (default), tap (default w/o term), tap13, junit, /<absolute path to formatter>
  • --filter-status <status> β€” Only run tests with the given status in the last completed (no Ctrl+C/SIGINT) run. Valid status values are:
    • failed β€” runs tests that failed or were not present in the last run
    • missed β€” runs tests that were not present in the last run
  • --filter-tags <comma-separated-tag-list> β€” Only run tests that match all the tags in the list (&&). You can negate a tag via prepending !. Specifying this flag multiple times allows for logical or (||): --filter-tags A,B --filter-tags A,!C matches tags (A && B) || (A && !C)
  • --gather-test-outputs-in <directory> β€” Gather the output of failing and passing tests as files in directory
  • -h, --help β€” Display this help message
  • -j, --jobs <jobs> β€” Number of parallel jobs (requires GNU parallel)
  • --negative-filter <regex> β€” Only run tests that do not match the regular expression
  • --no-tempdir-cleanup β€” Preserve test output temporary directory
  • --no-parallelize-across-files β€” Serialize test file execution instead of running them in parallel (requires --jobs >1)
  • --no-parallelize-within-files β€” Serialize test execution within files instead of running them in parallel (requires --jobs >1)
  • --parallel-binary-name <name> β€” Name of parallel binary
  • --report-formatter <type> β€” Switch between reporters (same options as --formatter)
  • -o, --output <dir> β€” Directory to write report files
  • -p, --pretty β€” Shorthand for "--formatter pretty"
  • --print-output-on-failure β€” Automatically print the value of $output on failed tests
  • -r, --recursive β€” Include tests in subdirectories
  • --show-output-of-passing-tests β€” Print output of passing tests
  • -t, --tap β€” Shorthand for "--formatter tap"
  • -T, --timing β€” Add timing information to tests
  • -x, --trace β€” Print test commands as they are executed (like set -x)
  • --verbose-run β€” Make run print $output by default
  • -v, --version β€” Display the version number

🌸 OUTPUT 🌸

When you run Bats from a terminal, you'll see output as each test is performed, with a check-mark next to the test's name if it passes β€” or an "X" if it fails. the check marks are literally the serotonin we deserve. ✨

$ bats addition.bats
 βœ“ addition using bc
 βœ“ addition using dc

2 tests, 0 failures

If Bats is not connected to a terminal β€” in other words, if you run it from a continuous integration system or redirect its output to a file β€” the results are displayed in human-readable, machine-parsable TAP format. You can force TAP output from a terminal by invoking Bats with the --tap option. πŸ–₯️

$ bats --tap addition.bats
1..2
ok 1 addition using bc
ok 2 addition using dc

🧚 EXIT STATUS 🧚

The bats interpreter exits with a value of 0 if all test cases pass, or 1 if one or more test cases fail. that's the whole chart, bestie. no nuance. 😌


πŸ‘‘ SEE ALSO πŸ‘‘


  • (c) 2017-2022 bats-core organization
  • (c) 2011-2016 Sam Stephenson

Bats is released under the terms of an MIT-style license. πŸŽ€


πŸ’– that's the whole page!! brought to you by bats-core, version dated July 2026, and yes she's still out here in section BATS(1) of your manual. go write some tests, you absolute icon. 🫢✨
πŸ“¦ where this page comes from