1BATS(7) Bash Automated Testing System BATS(7)
2
3
4
6 bats - Bats test file format
7
9 A Bats test file is a Bash script with special syntax for defining test
10 cases. Under the hood, each test case is just a function with a de‐
11 scription.
12
13
14
15 #!/usr/bin/env bats
16
17 @test "addition using bc" {
18 result="$(echo 2+2 | bc)"
19 [ "$result" -eq 4 ]
20 }
21
22 @test "addition using dc" {
23 result="$(echo 2 2+p | dc)"
24 [ "$result" -eq 4 ]
25 }
26
27
28
29 Each Bats test file is evaluated n+1 times, where n is the number of
30 test cases in the file. The first run counts the number of test cases,
31 then iterates over the test cases and executes each one in its own
32 process.
33
35 Usage: run [OPTIONS] [--] <command...> Options: ! check for non zero
36 exit code -N check that exit code is N --separate-stderr split stderr
37 and stdout --keep-empty-lines retain empty lines in
38 ${lines[@]}/${stderr_lines[@]}
39
40 Many Bats tests need to run a command and then make assertions about
41 its exit status and output. Bats includes a run helper that invokes its
42 arguments as a command, saves the exit status and output into special
43 global variables, and (optionally) checks exit status against a given
44 expected value. If successful, run returns with a 0 status code so you
45 can continue to make assertions in your test case.
46
47 For example, let´s say you´re testing that the foo command, when passed
48 a nonexistent filename, exits with a 1 status code and prints an error
49 message.
50
51
52
53 @test "invoking foo with a nonexistent file prints an error" {
54 run -1 foo nonexistent_filename
55 [ "$output" = "foo: no such file ´nonexistent_filename´" ]
56 }
57
58
59
60 The -1 as first argument tells run to expect 1 as an exit status, and
61 to fail if the command exits with any other value. On failure, both ac‐
62 tual and expected values will be displayed, along with the invoked com‐
63 mand and its output:
64
65
66
67 (in test file test.bats, line 2)
68 `run -1 foo nonexistent_filename´ failed, expected exit code 1, got 127
69
70
71
72 This error indicates a possible problem with the installation or con‐
73 figuration of foo; note that a simple [ $status != 0 ] test would not
74 have caught this kind of failure.
75
76 The $status variable contains the status code of the command, and the
77 $output variable contains the combined contents of the command´s stan‐
78 dard output and standard error streams.
79
80 A third special variable, the $lines array, is available for easily ac‐
81 cessing individual lines of output. For example, if you want to test
82 that invoking foo without any arguments prints usage information on the
83 first line:
84
85
86
87 @test "invoking foo without arguments prints usage" {
88 run -1 foo
89 [ "${lines[0]}" = "usage: foo <filename>" ]
90 }
91
92
93
94 By default run leaves out empty lines in ${lines[@]}. Use run
95 --keep-empty-lines to retain them.
96
97 Additionally, you can use --separate-stderr to split stdout and stderr
98 into $output/$stderr and ${lines[@]}/${stderr_lines[@]}.
99
100 All additional parameters to run should come before the command. If you
101 want to run a command that starts with -, prefix it with -- to prevent
102 run from parsing it as an option.
103
105 You may want to share common code across multiple test files. Bats in‐
106 cludes a convenient load command for sourcing a Bash source file rela‐
107 tive to the location of the current test file. For example, if you have
108 a Bats test in test/foo.bats, the command
109
110
111
112 load test_helper
113
114
115
116 will source the script test/test_helper.bash in your test file. This
117 can be useful for sharing functions to set up your environment or load
118 fixtures.
119
121 Some libraries are installed on the system, e.g. by npm or brew. These
122 should not be loaded, as their path depends on the installation method.
123 Instead, one should use bats_load_library together with setting
124 BATS_LIB_PATH, a PATH-like colon-delimited variable.
125
126 bats_load_library has two modes of resolving requests:
127
128 1. by relative path from the BATS_LIB_PATH to a file in the library
129
130 2. by library name, expecting libraries to have a load.bash entrypoint
131
132
133
134 For example if your BATS_LIB_PATH is set to ~/.bats/libs:/usr/lib/bats,
135 then bats_load_library test_helper would look for existing files with
136 the following paths:
137
138 • ~/.bats/libs/test_helper
139
140 • ~/.bats/libs/test_helper/load.bash
141
142 • /usr/lib/bats/test_helper
143
144 • /usr/lib/bats/test_helper/load.bash
145
146
147
148 The first existing file in this list will be sourced.
149
150 If you want to load only part of a library or the entry point is not
151 named load.bash, you have to include it in the argument: bats_load_li‐
152 brary library_name/file_to_load will try
153
154 • ~/.bats/libs/library_name/file_to_load
155
156 • ~/.bats/libs/library_name/file_to_load/load.bash
157
158 • /usr/lib/bats/library_name/file_to_load
159
160 • /usr/lib/bats/library_name/file_to_load/load.bash
161
162
163
164 Apart from the changed lookup rules, bats_load_library behaves like
165 load.
166
167 Note: As seen above load.bash is the entry point for libraries and
168 meant to load more files from its directory or other libraries.
169
170 Note: Obviously, the actual BATS_LIB_PATH is highly dependent on the
171 environment. To maintain a uniform location across systems, (distribu‐
172 tion) package maintainers are encouraged to use /usr/lib/bats/ as the
173 install path for libraries where possible. However, if the package man‐
174 ager has another preferred location, like npm or brew, you should use
175 this instead.
176
178 Tests can be skipped by using the skip command at the point in a test
179 you wish to skip.
180
181
182
183 @test "A test I don´t want to execute for now" {
184 skip
185 run -0 foo
186 }
187
188
189
190 Optionally, you may include a reason for skipping:
191
192
193
194 @test "A test I don´t want to execute for now" {
195 skip "This command will return zero soon, but not now"
196 run -0 foo
197 }
198
199
200
201 Or you can skip conditionally:
202
203
204
205 @test "A test which should run" {
206 if [ foo != bar ]; then
207 skip "foo isn´t bar"
208 fi
209
210 run -0 foo
211 }
212
213
214
216 Code for newer versions of Bats can be incompatible with older ver‐
217 sions. In the best case this will lead to an error message and a failed
218 test suite. In the worst case, the tests will pass erroneously, poten‐
219 tially masking a failure.
220
221 Use bats_require_minimum_version <Bats version number> to avoid this.
222 It communicates in a concise manner, that you intend the following code
223 to be run under the given Bats version or higher.
224
225 Additionally, this function will communicate the current Bats version
226 floor to subsequent code, allowing e.g. Bats´ internal warning to give
227 more informed warnings.
228
229 Note: By default, calling bats_require_minimum_version with versions
230 before Bats 1.7.0 will fail regardless of the required version as the
231 function is not available. However, you can use the bats-backports
232 plugin (https://github.com/bats-core/bats-backports) to make your code
233 usable with older versions, e.g. during migration while your CI system
234 is not yet upgraded.
235
237 You can define special setup and teardown functions which run before
238 and after each test case, respectively. Use these to load fixtures, set
239 up your environment, and clean up when you´re done.
240
242 You can include code in your test file outside of @test functions. For
243 example, this may be useful if you want to check for dependencies and
244 fail immediately if they´re not present. However, any output that you
245 print in code outside of @test, setup or teardown functions must be
246 redirected to stderr (>&2). Otherwise, the output may cause Bats to
247 fail by polluting the TAP stream on stdout.
248
250 There are several global variables you can use to introspect on Bats
251 tests:
252
253 • $BATS_TEST_FILENAME is the fully expanded path to the Bats test
254 file.
255
256 • $BATS_TEST_DIRNAME is the directory in which the Bats test file is
257 located.
258
259 • $BATS_TEST_NAMES is an array of function names for each test case.
260
261 • $BATS_TEST_NAME is the name of the function containing the current
262 test case.
263
264 • BATS_TEST_NAME_PREFIX will be prepended to the description of each
265 test on stdout and in reports.
266
267 • $BATS_TEST_DESCRIPTION is the description of the current test case.
268
269 • BATS_TEST_RETRIES is the maximum number of additional attempts that
270 will be made on a failed test before it is finally considered
271 failed. The default of 0 means the test must pass on the first at‐
272 tempt.
273
274 • $BATS_TEST_NUMBER is the (1-based) index of the current test case
275 in the test file.
276
277 • $BATS_SUITE_TEST_NUMBER is the (1-based) index of the current test
278 case in the test suite (over all files).
279
280 • $BATS_TMPDIR is the base temporary directory used by bats to create
281 its temporary files / directories. (default: $TMPDIR. If $TMPDIR is
282 not set, /tmp is used.)
283
284 • $BATS_RUN_TMPDIR is the location to the temporary directory used by
285 bats to store all its internal temporary files during the tests.
286 (default: $BATS_TMPDIR/bats-run-$BATS_ROOT_PID-XXXXXX)
287
288 • $BATS_FILE_EXTENSION (default: bats) specifies the extension of
289 test files that should be found when running a suite (via bats [-r]
290 suite_folder/)
291
292 • $BATS_SUITE_TMPDIR is a temporary directory common to all tests of
293 a suite. Could be used to create files required by multiple tests.
294
295 • $BATS_FILE_TMPDIR is a temporary directory common to all tests of a
296 test file. Could be used to create files required by multiple tests
297 in the same test file.
298
299 • $BATS_TEST_TMPDIR is a temporary directory unique for each test.
300 Could be used to create files required only for specific tests.
301
302 • $BATS_VERSION is the version of Bats running the test.
303
304
305
307 bash(1), bats(1)
308
309
310
311bats-core July 2022 BATS(7)