bew/dotfiles/coder-bats

Claude Code and agent skill by bew/dotfiles

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Bats test file writing guidelines: file structure, test naming, setup conventions, and helpers. Always load when asked to draft/write/edit/refactor/review .bats test files.

Install

npx vskill@latest install bew/dotfiles/coder-bats

SKILL.md

Goal

Write well-structured Bats test files following consistent naming, setup, and assertion conventions.

REQUIRES: load coder-generic skill first. REQUIRES: load coder-bash skill — function bodies in @test blocks and helpers follow bash conventions.

NOTE: Bats test files are written in bash, but can end-to-end test scripts/tools in any language — not just bash.

Rules

  • Name test file <script-name>.bats — same name as the script under test.
  • Always declare bats_require_minimum_version 1.5.0 after the header comment.
  • Use SCRIPT_DIR and SCRIPT_PATH globals to reference the tested script — never hardcode paths.
  • setup() must contain only preparation shared by ALL tests.

Test-specific setup goes inside the @test block itself.

  • Omit setup() entirely if nothing is shared across all tests.
  • Use setup_file() (runs once before all tests) for suite-wide isolation — e.g. stripping the

environment down to essential variables so tests don't leak from the caller's env. Do not use setup_file() for per-test preparation.

  • Use --keep-empty-lines on run when the script under test produces meaningful blank lines.

Without it, bats strips trailing blank lines from $output.

  • Test names must follow format "topic: summary".
  • Write helpers topic tests first in the file.
  • Use run -N to assert exit code inline (e.g. run -0, run -1).
  • When testing stderr output, use --separate-stderr flag on run.

Access stderr via $stderr, stdout via $output.

  • Custom assertion helpers must be prefixed assert_.
  • Test execution wrappers must be prefixed run_.
  • Setup helpers (beyond the shared setup()) must be prefixed setup_.
  • Never build arg strings dynamically (e.g. printf '%q ' "$@").

Pass "$@" through directly — it is always safe, including when empty.

  • When told to add a check "in each test", place it in each @test body.

Never collapse it into a shared helper to avoid repetition — the explicitness is intentional.

  • Never recompute expected values dynamically using the same tool the script under test uses.

When the test environment is fully controlled (known paths, fixed structure), hardcode expected values directly.

Test topics (canonical list)

Use these topic prefixes in test names:

TopicPurpose
helpersTests for custom assert_* helpers
defaultsDefault behavior without any flags
cliCommand-line argument and flag handling
errorError handling and validation
usageHelp/usage message output
edgeEdge cases and unusual inputs
integrationPiping, chaining with other tools

File header

bash
# Test suite for `<script-name>` script
#
# % Uses BATS testing system
# docs: https://bats-core.readthedocs.io/
# repo: https://github.com/bats-core/bats-core
#
# Run tests with: `bats $this_file [--filter foobar]`

File structure

bash
# [header comment]
bats_require_minimum_version 1.5.0
SCRIPT_DIR="$(dirname "$BATS_TEST_FILENAME")"
SCRIPT_PATH="$SCRIPT_DIR/<script-name>"
# Shared setup — omit entirely if nothing is shared across all tests
function setup() {
export SOME_VAR="for-all-tests"
}
# ------------------------------------------------------------------------------
# Tests: helpers
@test "helpers: assert_length works" { ... }
# ------------------------------------------------------------------------------
# Tests: defaults
@test "defaults: generates expected output" { ... }

Test examples

bash
@test "defaults: generates 32-char string" {
run -0 "$SCRIPT_PATH"
[[ "${#output}" -eq 32 ]]
}
@test "cli: accepts length as positional argument" {
run -0 "$SCRIPT_PATH" 16
[[ "${#output}" -eq 16 ]]
}
@test "error: rejects non-numeric length" {
run -1 --separate-stderr "$SCRIPT_PATH" abc
[[ "$stderr" == *"Error:"* ]]
}

Section separators

Group tests by topic using # Tests: <topic> headers:

bash
# ------------------------------------------------------------------------------
# Tests: cli

setup() patterns

If the script expects to run inside a specific directory structure (e.g. a git repo), cd into it in setup(). Tests then call run -0 "$SCRIPT_PATH" directly — no path juggling, no wrapper needed.

bash
function setup() {
TEST_REPO="$BATS_TEST_TMPDIR/repo"
mkdir -p "$TEST_REPO"
cd "$TEST_REPO"
git init -q
git config user.email "test@example.com"
git config user.name "Test"
}

run_script wrapper helpers

Define a wrapper only when it adds real logic — environment variables, input files, fixed flags, or other shared setup that every call needs. A purely pass-through wrapper is noise; don't define it.

When tests share non-trivial setup (e.g. creating an input file and setting an env var), define script-specific wrappers:

bash
# Run the script expecting success; creates input file and sets env var
function run_script() {
setup_test_input_file
GEN_RANDOM_SOURCE_FILE="$TEST_INPUT_FILE" run -0 --separate-stderr "$SCRIPT_PATH" "$@"
}
# Run the script expecting failure; exposes error log written by the script
function run_script_failed() {
local error_log="$BATS_TEST_TMPDIR/error.log"
run -1 --separate-stderr "$SCRIPT_PATH" --error-log "$error_log" "$@"
error_log_content="$(cat "$error_log" 2>/dev/null || true)"
}

These are script-specific — define them per .bats file, not as shared helpers.

JSON output testing

Always use jq to verify JSON output — never string-match raw JSON directly.

  • For small payloads (~100 chars or fewer): normalize with jq -c '.' and compare with an

exact compact string. Whitespace- and key-order-safe.

  • For large or dynamic payloads: use field-level jq queries instead of full-output comparison.

Example (small payload, exact compact match):

bash
@test "json: outputs empty array when no entries" {
run -0 --separate-stderr "$SCRIPT_PATH" --json
[[ "$(jq -c '.' <<< "$output")" == '[]' ]]
}

JSON fixtures

Build interpolated payloads with the printf -v single-quoted format from coder-bash, never with \" escapes. Skip the helper for a static payload used by one test — single-quote it inline.

Define a setup_<thing>_payload helper when more than one test needs the payload:

bash
function setup_profile_payload() {
local rev="$1"
# Global on purpose: the script under test reads it from the environment.
printf -v FAKE_PROFILE_JSON '{"profile":{"rev":"%s"}}' "$rev"
export FAKE_PROFILE_JSON
}

Running tests

bash
bats script.bats # all tests
bats script.bats -f "topic" # tests matching pattern

References

  • Bats docs: https://bats-core.readthedocs.io/en/stable/writing-tests.html

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/bew/dotfiles/coder-bats/badge)](https://verified-skill.com/skills/bew/dotfiles/coder-bats)

Something wrong with this skill or its page? Tell us.