Skills · Coding

Bats Testing Patterns

Unverified32/40

Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring test-driven development of shell utilities.

Originally by wshobson · MIT

Claude CodePartialHas SKILL.md but declares no allowed-tools — Claude Code will ask for permission each time
Cursor·UnknownWe have not crawled the repo tree, so we will not guess
Codex·UnknownWe have not crawled the repo tree, so we will not guess
Gemini CLI·UnknownThe spec defines no detection rule for Gemini
Copilot·UnknownWe have not crawled the repo tree, so we will not guess
npx agentalley add bats-testing-patterns

This command does not work yet — the CLI is still being built. Until then, use Raw in the reader below to take the file.

Who is stuck, and on what

Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring test-driven development of shell utilities.

The whole source

No sign-in, no blur, nothing truncated
bats-testing-patterns/SKILL.md230 lines5.1 KBRawView on GitHub
Frontmatter — 2 properties
namebats-testing-patterns
descriptionMaster Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring test-driven development of shell utilities.
1---
2name: bats-testing-patterns
3description: Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring test-driven development of shell utilities.
4---A5No allowed-tools declared — no way to tell what this skill may touch
5 
6# Bats Testing Patterns
7 
8Comprehensive guidance for writing comprehensive unit tests for shell scripts using Bats (Bash Automated Testing System), including test patterns, fixtures, and best practices for production-grade shell testing.
9 
10## When to Use This Skill
11 
12- Writing unit tests for shell scripts
13- Implementing test-driven development (TDD) for scripts
14- Setting up automated testing in CI/CD pipelines
15- Testing edge cases and error conditions
16- Validating behavior across different shell environments
17- Building maintainable test suites for scripts
18- Creating fixtures for complex test scenarios
19- Testing multiple shell dialects (bash, sh, dash)
20 
21## Detailed patterns and worked examples
22 
23Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
24 
25## Testing Error Conditions
26 
27```bash
28#!/usr/bin/env bats
29 
30@test "Function fails with missing file" {
31 run my_function "/nonexistent/file.txt"
32 [ "$status" -ne 0 ]
33 [[ "$output" == *"not found"* ]]
34}
35 
36@test "Function fails with invalid input" {
37 run my_function ""
38 [ "$status" -ne 0 ]
39}
40 
41@test "Function fails with permission denied" {
42 touch "$TMPDIR/readonly.txt"
43 chmod 000 "$TMPDIR/readonly.txt"
44 run my_function "$TMPDIR/readonly.txt"
45 [ "$status" -ne 0 ]
46 chmod 644 "$TMPDIR/readonly.txt" # Cleanup
47}
48 
49@test "Function provides helpful error message" {
50 run my_function --invalid-option
51 [ "$status" -ne 0 ]
52 [[ "$output" == *"Usage:"* ]]
53}
54```
55 
56### Testing with Dependencies
57 
58```bash
59#!/usr/bin/env bats
60 
61setup() {
62 # Check for required tools
63 if ! command -v jq &>/dev/null; then
64 skip "jq is not installed"
65 fi
66 
67 export SCRIPT="${BATS_TEST_DIRNAME}/../bin/script.sh"
68}
69 
70@test "JSON parsing works" {
71 skip_if ! command -v jq &>/dev/null
72 run my_json_parser '{"key": "value"}'
73 [ "$status" -eq 0 ]
74}
75```
76 
77### Testing Shell Compatibility
78 
79```bash
80#!/usr/bin/env bats
81 
82@test "Script works in bash" {
83 bash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
84}
85 
86@test "Script works in sh (POSIX)" {
87 sh "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
88}
89 
90@test "Script works in dash" {
91 if command -v dash &>/dev/null; then
92 dash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
93 else
94 skip "dash not installed"
95 fi
96}
97```
98 
99### Parallel Execution
100 
101```bash
102#!/usr/bin/env bats
103 
104@test "Multiple independent operations" {
105 run bash -c 'for i in {1..10}; do
106 my_operation "$i" &
107 done
108 wait'
109 [ "$status" -eq 0 ]
110}
111 
112@test "Concurrent file operations" {
113 for i in {1..5}; do
114 my_function "$TMPDIR/file$i" &
115 done
116 wait
117 [ -f "$TMPDIR/file1" ]
118 [ -f "$TMPDIR/file5" ]
119}
120```
121 
122## Test Helper Pattern
123 
124### test_helper.sh
125 
126```bash
127#!/usr/bin/env bash
128 
129# Source script under test
130export SCRIPT_DIR="${BATS_TEST_DIRNAME%/*}/bin"
131 
132# Common test utilities
133assert_file_exists() {
134 if [ ! -f "$1" ]; then
135 echo "Expected file to exist: $1"
136 return 1
137 fi
138}
139 
140assert_file_equals() {
141 local file="$1"
142 local expected="$2"
143 
144 if [ ! -f "$file" ]; then
145 echo "File does not exist: $file"
146 return 1
147 fi
148 
149 local actual=$(cat "$file")
150 if [ "$actual" != "$expected" ]; then
151 echo "File contents do not match"
152 echo "Expected: $expected"
153 echo "Actual: $actual"
154 return 1
155 fi
156}
157 
158# Create temporary test directory
159setup_test_dir() {
160 export TEST_DIR=$(mktemp -d)
161}
162 
163cleanup_test_dir() {
164 rm -rf "$TEST_DIR"
165}
166```
167 
168## Integration with CI/CD
169 
170### GitHub Actions Workflow
171 
172```yaml
173name: Tests
174 
175on: [push, pull_request]
176 
177jobs:
178 test:
179 runs-on: ubuntu-latest
180 
181 steps:
182 - uses: actions/checkout@v3
183 
184 - name: Install Bats
185 run: |
186 npm install --global bats
187 
188 - name: Run Tests
189 run: |
190 bats tests/*.bats
191 
192 - name: Run Tests with Tap Reporter
193 run: |
194 bats tests/*.bats --tap | tee test_output.tap
195```
196 
197### Makefile Integration
198 
199```makefile
200.PHONY: test test-verbose test-tap
201 
202test:
203 bats tests/*.bats
204 
205test-verbose:
206 bats tests/*.bats --verbose
207 
208test-tap:
209 bats tests/*.bats --tap
210 
211test-parallel:
212 bats tests/*.bats --parallel 4
213 
214coverage: test
215 # Optional: Generate coverage reports
216```
217 
218## Best Practices
219 
2201. **Test one thing per test** - Single responsibility principle
2212. **Use descriptive test names** - Clearly states what is being tested
2223. **Clean up after tests** - Always remove temporary files in teardown
2234. **Test both success and failure paths** - Don't just test happy path
2245. **Mock external dependencies** - Isolate unit under test
2256. **Use fixtures for complex data** - Makes tests more readable
2267. **Run tests in CI/CD** - Catch regressions early
2278. **Test across shell dialects** - Ensure portability
2289. **Keep tests fast** - Run in parallel when possible
22910. **Document complex test setup** - Explain unusual patterns
230 

Reviews

Installed this one?Write the first review and take the Trailblazer badge.

Reviews only open after a real install, so this is empty — and we leave it empty rather than invent one.

Alternatives

Also in Coding