Communitygithub.com

Jamie-BitFlight/bash-testing

此技能應在使用者要求「測試 bash 腳本」、「編寫 shell 測試」、「使用 shunit2」、「使用 shellspec」、「為 bash 建立測試套件」,或提及單元測試、測試框架、模擬或 shell 腳本的測試驅動開發時使用。

bash-testing 是什麼?

此技能提供針對 shell 腳本的完整測試策略,重點介紹 shunit2 與 shellspec 兩大框架。shunit2 採用 xUnit 風格,簡單可攜,適合單元測試與函式測試;shellspec 則為 BDD 風格,現代且功能豐富,適合完整專案的行為規格。技能涵蓋從安裝、基本測試結構、斷言與匹配器、隔離測試、模擬外部指令,到測試 stdout/stderr、fixtures、互動函式等實用模式,並提供最佳實踐建議。支援 Linux、macOS 等 Unix-like 環境,可透過 curl 或套件管理器安裝,適合所有需要為 bash 腳本建立自動化測試的開發者。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Jamie-BitFlight/claude_skills/tree/main/plugins/bash-development/skills/bash-testing

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Bash 測試

用於 shell 腳本的測試框架與模式,重點在於 shunit2 與 shellspec。

框架選擇

框架優勢最適用於
shunit2xUnit 風格、簡單、可攜單元測試、函式測試
shellspecBDD 風格、現代、功能豐富行為規格、完整專案

shunit2

安裝

# 直接下載
curl -L https://github.com/kward/shunit2/raw/master/shunit2 -o shunit2

# 或透過套件管理器
apt install shunit2
brew install shunit2

基本測試結構

#!/usr/bin/env bash

# 匯入待測腳本
source ./my_script.sh

# 測試函式以 test 開頭
test_addition() {
    result=$(add 2 3)
    assertEquals "2 + 3 應等於 5" "5" "$result"
}

test_string_output() {
    result=$(greet "World")
    assertEquals "Hello, World" "$result"
}

test_file_creation() {
    create_temp_file
    assertTrue "暫存檔應存在" "[ -f /tmp/testfile ]"
}

test_exit_code() {
    validate_input "valid"
    assertEquals "有效輸入應回傳 0" 0 $?
}

# 設定與清理
oneTimeSetUp() {
    # 在所有測試前執行一次
    export TEST_DIR=$(mktemp -d)
}

oneTimeTearDown() {
    # 在所有測試後執行一次
    rm -rf "$TEST_DIR"
}

setUp() {
    # 每個測試前執行
    cd "$TEST_DIR"
}

tearDown() {
    # 每個測試後執行
    rm -f "$TEST_DIR"/*
}

# 載入 shunit2
source shunit2

shunit2 斷言

# 相等性
assertEquals [訊息] 預期值 實際值
assertNotEquals [訊息] 不預期值 實際值

# 空值/非空值
assertNull [訊息] 值
assertNotNull [訊息] 值

# 布林值/狀態
assertTrue [訊息] 條件
assertFalse [訊息] 條件

# 相同參考(字串比較)
assertSame [訊息] 預期值 實際值
assertNotSame [訊息] 不預期值 實際值

# 包含(於字串中)
assertContains [訊息] 容器 內容

# 離開狀態
assertEquals 0 $?

孤立測試函式

程式碼範例

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

source ./my_functions.sh

test_calculate_sum_empty() {
    result=$(calculate_sum)
    assertEquals "空總和應為 0" "0" "$result"
}

test_calculate_sum_single() {
    result=$(calculate_sum 5)
    assertEquals "5" "$result"
}

test_calculate_sum_multiple() {
    result=$(calculate_sum 1 2 3 4 5)
    assertEquals "15" "$result"
}

test_validate_email_valid() {
    validate_email "[email protected]"
    assertTrue "有效 email 應通過" $?
}

test_validate_email_invalid() {
    validate_email "not-an-email"
    assertFalse "無效 email 應失敗" $?
}

source shunit2

shellspec

安裝

# 透過 curl
curl -fsSL https://git.io/shellspec | sh

# 透過 Homebrew
brew install shellspec

# 透過套件管理器
apt install shellspec

目錄結構

project/
├── lib/
│   └── functions.sh
├── spec/
│   ├── spec_helper.sh
│   ├── functions_spec.sh
│   └── support/
│       └── fixtures/
└── .shellspec

設定檔 (.shellspec)

--require spec_helper
--format documentation
--color

基本規格結構

程式碼範例

shellspec 匹配器

# 輸出匹配器
The output should eq "完全比對"
The output should include "部分包含"
The output should start with "前綴"
The output should end with "後綴"
The output should match pattern "*glob*"
The output should be blank

# 狀態匹配器
The status should be success    # 離開碼 0
The status should be failure    # 離開碼非零
The status should eq 1          # 特定碼

# 變數匹配器
The variable VAR should eq "值"
The variable VAR should be defined
The variable VAR should be undefined

# 檔案匹配器
The file "路徑" should be exist
The file "路徑" should be file
The file "路徑" should be directory
The file "路徑" should be readable

# 路徑匹配器
The path "file.txt" should be exist

在 shellspec 中模擬

Describe 'deploy 函式'
  # 模擬外部指令
  curl() {
    echo "模擬回應"
    return 0
  }

  It '呼叫 API 端點'
    When call deploy "server"
    The output should include "模擬回應"
  End
End

Describe '檔案操作'
  # 透過函式覆寫進行模擬
  Mock rm
    echo "rm 被呼叫,參數為:$*"
  End

  It '嘗試移除檔案'
    When call cleanup_temp
    The output should include "rm 被呼叫,參數為:"
  End
End

規格助手

# spec/spec_helper.sh

# 載入通用函式
spec_helper_precheck() {
  minimum_version "0.28.0"
}

spec_helper_loaded() {
  # 設定測試環境
  export TEST_MODE=true
}

spec_helper_configure() {
  # 匯入專案函式
  import 'lib/functions.sh'
}

測試模式

測試離開碼

# shunit2
test_success_exit() {
    run_command "valid_input"
    assertEquals 0 $?
}

test_error_exit() {
    run_command "invalid_input"
    assertEquals 1 $?
}

# shellspec
It '成功時離開碼為 0'
  When call run_command "valid_input"
  The status should eq 0
End

測試 stdout 與 stderr

# shunit2
test_stdout() {
    result=$(my_function 2>/dev/null)
    assertEquals "預期輸出" "$result"
}

test_stderr() {
    error=$(my_function 2>&1 >/dev/null)
    assertContains "$error" "錯誤訊息"
}

# shellspec
It '輸出至 stdout'
  When call my_function
  The stdout should eq "預期輸出"
End

It '將錯誤輸出至 stderr'
  When call my_function
  The stderr should include "錯誤訊息"
End

使用 Fixtures 測試

# 設定測試 Fixtures
setUp() {
    TEST_DIR=$(mktemp -d)
    cat > "$TEST_DIR/config.json" <<EOF
{
    "key": "value"
}
EOF
}

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

test_config_parsing() {
    result=$(parse_config "$TEST_DIR/config.json")
    assertEquals "value" "$result"
}

測試互動式函式

# 透過 heredoc 提供輸入
test_interactive() {
    result=$(my_prompt <<EOF
yes
EOF
)
    assertEquals "confirmed" "$result"
}

# 或使用 printf
test_with_input() {
    result=$(printf 'yes\n' | my_prompt)
    assertEquals "confirmed" "$result"
}

執行測試

# shunit2
./test_script.sh

# shellspec
shellspec                    # 執行所有規格
shellspec spec/file_spec.sh  # 執行特定規格
shellspec --format tap       # TAP 輸出
shellspec --jobs 4           # 並行執行

最佳實踐

  1. 盡量一個測試一個斷言
  2. 描述性測試名稱,說明測試內容
  3. 隔離測試 – 測試之間不應有依賴
  4. 測試邊界情況 – 空輸入、特殊字元、大量資料
  5. 在 tearDown 中清理資源
  6. 模擬外部指令 – 不要測試 curl,測試你的邏輯
  7. 測試離開碼而不僅僅是輸出

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

Jamie-BitFlight/agentskill-kaizen-meta-docs

Agentskill kaizen plugin documentation index. Load when needing to read about cross-platform notes, improvement plans, or DuckDB integration.

Jamie-BitFlight/bash-51-features

Bash 5.1 release features and improvements with practical examples. Use when working with Bash 5.1 features, epoch time variables, redirection enhancements, or when user asks about Bash 5.1 changes, new features, or version-specific capabilities.

Jamie-BitFlight/bash-52-features

Bash 5.2 release features and improvements with practical examples. Use when working with Bash 5.2 features, variable handling enhancements, readline improvements, or when user asks about Bash 5.2 changes, new features, or version-specific capabilities.

Jamie-BitFlight/bash-53-features

Bash 5.3 release features and improvements with practical examples. Use when working with Bash 5.3 features, new command substitution, GLOBSORT, loadable builtins, or when user asks about Bash 5.3 changes, new features, or version-specific capabilities.

Jamie-BitFlight/bash-development

This skill should be used when the user asks to "write a bash script", "create a shell script", "implement bash function", "parse arguments in bash", "handle errors in bash", or mentions bash development, shell scripting, script templates, or modern bash patterns.

Jamie-BitFlight/bash-lint

This skill should be used when the user asks to "lint bash script", "run shellcheck", "format shell script", "use shfmt", "fix shellcheck errors", or mentions shell script linting, formatting, code quality, or pre-commit hooks for bash.

Jamie-BitFlight/bash-logging

This skill should be used when the user asks to "add logging to bash script", "colorize output", "implement log levels", "CI/CD sections", "terminal colors in bash", or mentions logging functions, emoji output, collapsible CI sections, or shlocksmith.

Jamie-BitFlight/bash-portability

This skill should be used when the user asks about "POSIX compatibility", "portable shell scripts", "cross-shell compatibility", "bashisms", "shebang selection", or mentions writing scripts that work on different shells (bash, sh, dash, zsh) or different systems.

Jamie-BitFlight/brainstorming-skill

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or when users request help with ideation, marketing, and strategic planning. Explores user intent, requirements, and design before implementation using research-validated prompt patterns.

Jamie-BitFlight/clang-format

Configure clang-format code formatting. Use when: user mentions clang-format or .clang-format, analyzing code style/patterns, creating/modifying formatting config, troubleshooting formatting, brace styles/indentation/spacing/alignment/pointer alignment, or codifying conventions.

Jamie-BitFlight/commitlint

When setting up commit message validation for a project. When project has commitlint.config.js or .commitlintrc files. When configuring CI/CD to enforce commit format. When extracting commit rules for LLM prompt generation. When debugging commit message rejection errors.

Jamie-BitFlight/conventional-commits

When writing a git commit message. When task completes and changes need committing. When project uses semantic-release, commitizen, git-cliff. When choosing between feat/fix/chore/docs types. When indicating breaking changes. When generating changelogs from commit history.

Jamie-BitFlight/dasel-reference

Use when querying, modifying, or converting JSON, YAML, TOML, XML, CSV, HCL, or INI with dasel v3. Complete reference for selectors, functions, conditionals, variables, spread operator, type casting, and format-specific patterns.

Jamie-BitFlight/data-exploration

Use when exploring unknown structured data files with dasel v3 — discover schema, list keys, find nested values, sample arrays, identify data types across JSON, YAML, TOML, XML, CSV, HCL, INI formats

Jamie-BitFlight/data-transformation

Use when modifying, converting, or transforming structured data with dasel v3 — in-place mutations, format conversion, batch operations, array manipulation, object construction, and merge patterns across JSON, YAML, TOML, XML, CSV, HCL, INI

Jamie-BitFlight/delegate

Decompose substantive work into phases, dispatch each phase to a sub-agent, and adjudicate what comes back. Use whenever a request asks for implementation, investigation, a fix, a review, or any change to files — including small ones — and whenever you are about to read source or run a diagnostic yourself instead of handing it off. Also use when a report from a sub-agent needs judging, when a phase needs re-dispatching, or when a user names one instance of a pattern. Does not apply when your own prompt begins "Your ROLE_TYPE is sub-agent." — then follow references/sub-agent-contract.md instead.

Jamie-BitFlight/enterprise-hibernate-hbm

Dasel v3 query patterns for Hibernate .hbm.xml mapping files — entity-table binding, Java property-to-column extraction, one-to-many set/list/bag relationship tracing, many-to-one foreign key discovery, batch scanning across 60+ HBM files. Use when querying Hibernate ORM class mappings, extracting schema metadata from Java persistence layer, or auditing entity-column relationships in enterprise legacy codebases.

Jamie-BitFlight/enterprise-installanywhere

Dasel v3 query patterns for InstallAnywhere .iap_xml installer definitions — use when querying action sequences, discovering variables, resolving platform conditions, navigating panels, or comparing installer variants. Files are 2.5+ MB, 65,000+ lines — too large for context reads, requires structural dasel queries.

Jamie-BitFlight/enterprise-maven-pom

Dasel v3 selector patterns for Maven POM XML files — use when querying dependency versions, filtering by groupId or scope, extracting module hierarchy from parent POMs, or detecting version conflicts across enterprise multi-module Java projects. Load this skill when working with pom.xml files using dasel.

Jamie-BitFlight/enterprise-spring-xml

Dasel v3 selectors for Spring bean factory XML — use when querying any Spring ApplicationContext XML for bean discovery, dependency wiring, JMS destination mapping, property injection extraction, or cross-bean reference tracing. Load this skill before writing dasel selectors against Spring bean XML files (applicationContext.xml, *_beans.xml, spring-*.xml).

相關技能