mcpField
B
bats-testing-patterns

bats-testing-patterns

github.com/wshobsonテスト・品質41.9k11.1k 回インストール2 週間前に更新
リポジトリ

bats-testing-patterns について

Bats でシェルスクリプトをテストする開発者向けのスキルです。テストパターン、フィクスチャ、エラー処理、シェル互換性、自動化連携を扱います。

主な機能

  1. 01シェルスクリプトのユニットテストパターン
  2. 02テストフィクスチャとヘルパー関数
  3. 03エラー条件と境界ケースのテスト
  4. 04シェル方言の互換性テスト
  5. 05CI/CD と Makefile の連携

活用シーン

  1. 01シェルスクリプトのユニットテスト作成
  2. 02エラー処理と外部依存関係の検証
  3. 03CI/CD でのスクリプトテスト実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshobson/agents --skill bats-testing-patterns

インストール後、Claude Code で/bats-testing-patternsを入力して読み込まれたか確認します。

同梱ファイルreferences/details.md

詳細

Bats テストパターン

Bats(Bash Automated Testing System)を使用してシェルスクリプト用の包括的な単体テストを作成するための総合的なガイダンスです。テストパターン、フィクスチャ、本番品質のシェルテストのベストプラクティスを含みます。

このスキルを使用する場面

  • シェルスクリプトの単体テストを作成する場合
  • スクリプトのテスト駆動開発(TDD)を実践する場合
  • CI/CD パイプラインで自動テストを設定する場合
  • エッジケースやエラー条件をテストする場合
  • 異なるシェル環境間での動作を検証する場合
  • スクリプト用の保守可能なテストスイートを構築する場合
  • 複雑なテストシナリオ用のフィクスチャを作成する場合
  • 複数のシェル方言(bash、sh、dash)をテストする場合

詳細なパターンと実例

詳細なパターンのドキュメントは references/details.md にあります。上記のナビゲーション階層では不十分な場合は、そのファイルを参照してください。

エラー条件のテスト

#!/usr/bin/env bats

@test "Function fails with missing file" {
    run my_function "/nonexistent/file.txt"
    [ "$status" -ne 0 ]
    [[ "$output" == *"not found"* ]]
}

@test "Function fails with invalid input" {
    run my_function ""
    [ "$status" -ne 0 ]
}

@test "Function fails with permission denied" {
    touch "$TMPDIR/readonly.txt"
    chmod 000 "$TMPDIR/readonly.txt"
    run my_function "$TMPDIR/readonly.txt"
    [ "$status" -ne 0 ]
    chmod 644 "$TMPDIR/readonly.txt"  # Cleanup
}

@test "Function provides helpful error message" {
    run my_function --invalid-option
    [ "$status" -ne 0 ]
    [[ "$output" == *"Usage:"* ]]
}
依存関係を使用したテスト
#!/usr/bin/env bats

setup() {
    # Check for required tools
    if ! command -v jq &>/dev/null; then
        skip "jq is not installed"
    fi

    export SCRIPT="${BATS_TEST_DIRNAME}/../bin/script.sh"
}

@test "JSON parsing works" {
    skip_if ! command -v jq &>/dev/null
    run my_json_parser '{"key": "value"}'
    [ "$status" -eq 0 ]
}
シェル互換性のテスト
#!/usr/bin/env bats

@test "Script works in bash" {
    bash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
}

@test "Script works in sh (POSIX)" {
    sh "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
}

@test "Script works in dash" {
    if command -v dash &>/dev/null; then
        dash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
    else
        skip "dash not installed"
    fi
}
並列実行
#!/usr/bin/env bats

@test "Multiple independent operations" {
    run bash -c 'for i in {1..10}; do
        my_operation "$i" &
    done
    wait'
    [ "$status" -eq 0 ]
}

@test "Concurrent file operations" {
    for i in {1..5}; do
        my_function "$TMPDIR/file$i" &
    done
    wait
    [ -f "$TMPDIR/file1" ]
    [ -f "$TMPDIR/file5" ]
}

テストヘルパーパターン

test_helper.sh
#!/usr/bin/env bash

# Source script under test
export SCRIPT_DIR="${BATS_TEST_DIRNAME%/*}/bin"

# Common test utilities
assert_file_exists() {
    if [ ! -f "$1" ]; then
        echo "Expected file to exist: $1"
        return 1
    fi
}

assert_file_equals() {
    local file="$1"
    local expected="$2"

    if [ ! -f "$file" ]; then
        echo "File does not exist: $file"
        return 1
    fi

    local actual=$(cat "$file")
    if [ "$actual" != "$expected" ]; then
        echo "File contents do not match"
        echo "Expected: $expected"
        echo "Actual: $actual"
        return 1
    fi
}

# Create temporary test directory
setup_test_dir() {
    export TEST_DIR=$(mktemp -d)
}

cleanup_test_dir() {
    rm -rf "$TEST_DIR"
}

CI/CD との統合

GitHub Actions ワークフロー
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Install Bats
        run: |
          npm install --global bats

      - name: Run Tests
        run: |
          bats tests/*.bats

      - name: Run Tests with Tap Reporter
        run: |
          bats tests/*.bats --tap | tee test_output.tap
Makefile との統合
.PHONY: test test-verbose test-tap

test:
	bats tests/*.bats

test-verbose:
	bats tests/*.bats --verbose

test-tap:
	bats tests/*.bats --tap

test-parallel:
	bats tests/*.bats --parallel 4

coverage: test
	# Optional: Generate coverage reports

ベストプラクティス

  1. 1 つのテストで 1 つのことだけをテストする - 単一責任の原則
  2. 説明的なテスト名を使用する - 何をテストしているかを明確に示します
  3. テスト後にクリーンアップする - teardown で常に一時ファイルを削除します
  4. 成功パスと失敗パスの両方をテストする - ハッピーパスだけをテストしないでください
  5. 外部依存関係をモックする - テスト対象の単体を分離します
  6. 複雑なデータにはフィクスチャを使用する - テストがより読みやすくなります
  7. CI/CD でテストを実行する - リグレッションを早期に検出します
  8. シェル方言をまたいでテストする - 移植性を確保します
  9. テストを高速に保つ - 可能な場合は並列で実行します
  10. 複雑なテスト設定を文書化する - 特殊なパターンを説明します

コメント