Introduction
Bats (Bash Automated Testing System) is a testing framework for Bash scripts and command-line tools. Each test is a Bash function prefixed with @test, and assertions use standard Bash test constructs. Output follows the TAP (Test Anything Protocol) format for integration with CI systems.
What Bats Does
- Runs test cases written as annotated Bash functions in
.batsfiles - Produces TAP-compatible output for CI and test aggregation tools
- Supports setup and teardown functions at the file and test level
- Provides helper libraries for assertions, file operations, and output matching
- Runs tests in parallel for faster execution on large test suites
Architecture Overview
Bats preprocesses each .bats file, extracting @test blocks into individual Bash functions. Each test runs in its own subshell to ensure isolation. The test runner collects exit codes and output, then formats results as TAP. Helper libraries (bats-assert, bats-support, bats-file) provide higher-level assertion functions that produce informative failure messages.
Self-Hosting & Configuration
- Install via npm (
npm install -g bats), Homebrew, or clone the repository and run./install.sh - Place test files with the
.batsextension in atest/directory - Load helper libraries with
bats_load_libraryorloadcommands in each test file - Use
setup_fileandteardown_filefor one-time per-file initialization and cleanup - Run tests in parallel with
bats --jobs Nfor faster feedback
Key Features
- Simple syntax using standard Bash test expressions and commands
- TAP-compliant output that works with any TAP consumer or CI system
- Test isolation via subshells preventing state leakage between tests
- Parallel test execution with the
--jobsflag - Official helper libraries: bats-assert for assertions, bats-file for filesystem checks, bats-support for utilities
Comparison with Similar Tools
- ShellCheck — a static linter for shell scripts; Bats is a runtime test framework that verifies behavior
- shunit2 — an older xUnit-style testing framework for Bash; Bats offers simpler syntax and TAP output
- BATS (original) — the unmaintained predecessor; bats-core is the actively maintained community fork
- pytest with subprocess — usable for testing CLI tools from Python; Bats keeps tests in native Bash
FAQ
Q: Can Bats test any command-line program, not just Bash scripts? A: Yes. Bats can test any program that runs from the command line. Tests invoke commands and check exit codes and output.
Q: How do I share setup across multiple test files?
A: Use setup_file and teardown_file within each file, or create a common helper file loaded with the load command.
Q: Does Bats support test filtering?
A: Yes. Use bats --filter "pattern" to run only tests whose names match the given regex.
Q: Can I generate JUnit XML output for CI?
A: Yes. Use the --formatter junit flag or the bats-junit-formatter to produce JUnit-compatible XML reports.