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 #!/usr/bin/env bats
15
16 @test "addition using bc" {
17 result="$(echo 2+2 | bc)"
18 [ "$result" -eq 4 ]
19 }
20
21 @test "addition using dc" {
22 result="$(echo 2 2+p | dc)"
23 [ "$result" -eq 4 ]
24 }
25
26
27
28 Each Bats test file is evaluated n+1 times, where n is the number of
29 test cases in the file. The first run counts the number of test cases,
30 then iterates over the test cases and executes each one in its own
31 process.
32
34 Each test has a list of tags attached to it. Without specification,
35 this list is empty. Tags can be defined in two ways. The first being #
36 bats test_tags=:
37
38 # bats test_tags=tag:1, tag:2, tag:3 @test "second test" { # ... }
39
40 @test "second test" { # ... }
41
42 These tags (tag:1, tag:2, tag:3) will be attached to the test first
43 test. The second test will have no tags attached. Values defined in the
44 # bats test_tags= directive will be assigned to the next @test that is
45 being encountered in the file and forgotten after that. Only the value
46 of the last # bats test_tags= directive before a given test will be
47 used.
48
49 Sometimes, we want to give all tests in a file a set of the same tags.
50 This can be achieved via # bats file_tags=. They will be added to all
51 tests in the file after that directive. An additional # bats file_tags=
52 directive will override the previously defined values:
53
54
55 @test "Zeroth test" {
56 # will have no tags
57 }
58
59 # bats file_tags=a:b
60 # bats test_tags=c:d
61
62 @test "First test" {
63 # will be tagged a:b, c:d
64 }
65
66 # bats file_tags=
67
68 @test "Second test" {
69 # will have no tags
70 }
71
72
73
74 Tags are case sensitive and must only consist of alphanumeric charac‐
75 ters and _, -, or :. They must not contain whitespaces! The colon is
76 intended as a separator for (recursive) namespacing.
77
78 Tag lists must be separated by commas and are allowed to contain white‐
79 space. They must not contain empty tags like test_tags=,b (first tag is
80 empty), test_tags=a,,c, test_tags=a, ,c (second tag is only white‐
81 space/empty), test_tags=a,b, (third tag is empty).
82
83 Every tag starting with bats: (case insensitive!) is reserved for Bats´
84 internal use:
85
86 bats:focus
87 If any test with the tag bats:focus is encountered in a test
88 suite, only those tagged with this tag will be executed. To pre‐
89 vent the CI from silently running on a subset of tests due to an
90 accidentally commited bats:focus tag, the exit code of success‐
91 ful runs will be overriden to 1.
92
93 Should you require the true exit code, e.g. for a git bisect op‐
94 eration, you can disable this behavior by setting
95 BATS_NO_FAIL_FOCUS_RUN=1 when running bats, but make sure to not
96 commit this to CI!
97
99 Usage: run [OPTIONS] [--]
100
101 Many Bats tests need to run a command and then make assertions about
102 its exit status and output. Bats includes a run helper that invokes its
103 arguments as a command, saves the exit status and output into special
104 global variables, and (optionally) checks exit status against a given
105 expected value. If successful, run returns with a 0 status code so you
106 can continue to make assertions in your test case.
107
108 For example, let´s say you´re testing that the foo command, when passed
109 a nonexistent filename, exits with a 1 status code and prints an error
110 message.
111
112
113 @test "invoking foo with a nonexistent file prints an error" {
114 run -1 foo nonexistent_filename
115 [ "$output" = "foo: no such file ´nonexistent_filename´" ]
116 }
117
118
119
120 The -1 as first argument tells run to expect 1 as an exit status, and
121 to fail if the command exits with any other value. On failure, both ac‐
122 tual and expected values will be displayed, along with the invoked com‐
123 mand and its output:
124
125
126 (in test file test.bats, line 2)
127 `run -1 foo nonexistent_filename´ failed, expected exit code 1, got 127
128
129
130
131 This error indicates a possible problem with the installation or con‐
132 figuration of foo; note that a simple [ $status != 0 ] test would not
133 have caught this kind of failure.
134
135 The $status variable contains the status code of the command, and the
136 $output variable contains the combined contents of the command´s stan‐
137 dard output and standard error streams.
138
139 A third special variable, the $lines array, is available for easily ac‐
140 cessing individual lines of output. For example, if you want to test
141 that invoking foo without any arguments prints usage information on the
142 first line:
143
144
145 @test "invoking foo without arguments prints usage" {
146 run -1 foo
147 [ "${lines[0]}" = "usage: foo <filename>" ]
148 }
149
150
151
152 By default run leaves out empty lines in ${lines[@]}. Use run
153 --keep-empty-lines to retain them.
154
155 Additionally, you can use --separate-stderr to split stdout and stderr
156 into $output/$stderr and ${lines[@]}/${stderr_lines[@]}.
157
158 All additional parameters to run should come before the command. If you
159 want to run a command that starts with -, prefix it with -- to prevent
160 run from parsing it as an option.
161
163 You may want to share common code across multiple test files. Bats in‐
164 cludes a convenient load command for sourcing a Bash source file rela‐
165 tive to the location of the current test file. For example, if you have
166 a Bats test in test/foo.bats, the command
167
168
169 load test_helper
170
171
172
173 will source the script test/test_helper.bash in your test file. This
174 can be useful for sharing functions to set up your environment or load
175 fixtures.
176
178 Some libraries are installed on the system, e.g. by npm or brew. These
179 should not be loaded, as their path depends on the installation method.
180 Instead, one should use bats_load_library together with setting
181 BATS_LIB_PATH, a PATH-like colon-delimited variable.
182
183 bats_load_library has two modes of resolving requests:
184
185 1. by relative path from the BATS_LIB_PATH to a file in the library
186
187 2. by library name, expecting libraries to have a load.bash entrypoint
188
189
190
191 For example if your BATS_LIB_PATH is set to ~/.bats/libs:/usr/lib/bats,
192 then bats_load_library test_helper would look for existing files with
193 the following paths:
194
195 ○ ~/.bats/libs/test_helper
196
197 ○ ~/.bats/libs/test_helper/load.bash
198
199 ○ /usr/lib/bats/test_helper
200
201 ○ /usr/lib/bats/test_helper/load.bash
202
203
204
205 The first existing file in this list will be sourced.
206
207 If you want to load only part of a library or the entry point is not
208 named load.bash, you have to include it in the argument: bats_load_li‐
209 brary library_name/file_to_load will try
210
211 ○ ~/.bats/libs/library_name/file_to_load
212
213 ○ ~/.bats/libs/library_name/file_to_load/load.bash
214
215 ○ /usr/lib/bats/library_name/file_to_load
216
217 ○ /usr/lib/bats/library_name/file_to_load/load.bash
218
219
220
221 Apart from the changed lookup rules, bats_load_library behaves like
222 load.
223
224 Note: As seen above load.bash is the entry point for libraries and
225 meant to load more files from its directory or other libraries.
226
227 Note: Obviously, the actual BATS_LIB_PATH is highly dependent on the
228 environment. To maintain a uniform location across systems, (distribu‐
229 tion) package maintainers are encouraged to use /usr/lib/bats/ as the
230 install path for libraries where possible. However, if the package man‐
231 ager has another preferred location, like npm or brew, you should use
232 this instead.
233
235 Tests can be skipped by using the skip command at the point in a test
236 you wish to skip.
237
238
239 @test "A test I don´t want to execute for now" {
240 skip
241 run -0 foo
242 }
243
244
245
246 Optionally, you may include a reason for skipping:
247
248
249 @test "A test I don´t want to execute for now" {
250 skip "This command will return zero soon, but not now"
251 run -0 foo
252 }
253
254
255
256 Or you can skip conditionally:
257
258
259 @test "A test which should run" {
260 if [ foo != bar ]; then
261 skip "foo isn´t bar"
262 fi
263
264 run -0 foo
265 }
266
267
268
270 Code for newer versions of Bats can be incompatible with older ver‐
271 sions. In the best case this will lead to an error message and a failed
272 test suite. In the worst case, the tests will pass erroneously, poten‐
273 tially masking a failure.
274
275 Use bats_require_minimum_version <Bats version number> to avoid this.
276 It communicates in a concise manner, that you intend the following code
277 to be run under the given Bats version or higher.
278
279 Additionally, this function will communicate the current Bats version
280 floor to subsequent code, allowing e.g. Bats´ internal warning to give
281 more informed warnings.
282
283 Note: By default, calling bats_require_minimum_version with versions
284 before Bats 1.7.0 will fail regardless of the required version as the
285 function is not available. However, you can use the bats-backports
286 plugin (https://github.com/bats-core/bats-backports) to make your code
287 usable with older versions, e.g. during migration while your CI system
288 is not yet upgraded.
289
291 You can define special setup and teardown functions which run before
292 and after each test case, respectively. Use these to load fixtures, set
293 up your environment, and clean up when you´re done.
294
296 You can include code in your test file outside of @test functions. For
297 example, this may be useful if you want to check for dependencies and
298 fail immediately if they´re not present. However, any output that you
299 print in code outside of @test, setup or teardown functions must be
300 redirected to stderr (>&2). Otherwise, the output may cause Bats to
301 fail by polluting the TAP stream on stdout.
302
304 There are several global variables you can use to introspect on Bats
305 tests:
306
307 ○ $BATS_TEST_FILENAME is the fully expanded path to the Bats test
308 file.
309
310 ○ $BATS_TEST_DIRNAME is the directory in which the Bats test file is
311 located.
312
313 ○ $BATS_TEST_NAMES is an array of function names for each test case.
314
315 ○ $BATS_TEST_NAME is the name of the function containing the current
316 test case.
317
318 ○ BATS_TEST_NAME_PREFIX will be prepended to the description of each
319 test on stdout and in reports.
320
321 ○ $BATS_TEST_DESCRIPTION is the description of the current test case.
322
323 ○ BATS_TEST_RETRIES is the maximum number of additional attempts that
324 will be made on a failed test before it is finally considered
325 failed. The default of 0 means the test must pass on the first at‐
326 tempt.
327
328 ○ BATS_TEST_TIMEOUT is the number of seconds after which a test (in‐
329 cluding setup) will be aborted and marked as failed. Updates to
330 this value in setup() or @test cannot change the running timeout
331 countdown, so the latest useful update location is setup_file().
332
333 ○ $BATS_TEST_NUMBER is the (1-based) index of the current test case
334 in the test file.
335
336 ○ $BATS_SUITE_TEST_NUMBER is the (1-based) index of the current test
337 case in the test suite (over all files).
338
339 ○ $BATS_TMPDIR is the base temporary directory used by bats to create
340 its temporary files / directories. (default: $TMPDIR. If $TMPDIR is
341 not set, /tmp is used.)
342
343 ○ $BATS_RUN_TMPDIR is the location to the temporary directory used by
344 bats to store all its internal temporary files during the tests.
345 (default: $BATS_TMPDIR/bats-run-$BATS_ROOT_PID-XXXXXX)
346
347 ○ $BATS_FILE_EXTENSION (default: bats) specifies the extension of
348 test files that should be found when running a suite (via bats [-r]
349 suite_folder/)
350
351 ○ $BATS_SUITE_TMPDIR is a temporary directory common to all tests of
352 a suite. Could be used to create files required by multiple tests.
353
354 ○ $BATS_FILE_TMPDIR is a temporary directory common to all tests of a
355 test file. Could be used to create files required by multiple tests
356 in the same test file.
357
358 ○ $BATS_TEST_TMPDIR is a temporary directory unique for each test.
359 Could be used to create files required only for specific tests.
360
361 ○ $BATS_VERSION is the version of Bats running the test.
362
363
364
366 bash(1), bats(1)
367
368
369
370bats-core November 2022 BATS(7)