强大的Bash自动化测试框架Bats-core

13 阅读2分钟

Bats-core: Bash自动化测试系统

Bats-core是一个符合TAP标准的Bash测试框架,支持Bash 3.2及以上版本。它提供了一种简单的方法来验证您编写的UNIX程序是否按预期行为运行。

功能特性

  • TAP兼容测试输出:生成标准化的测试输出格式
  • 简洁的测试语法:使用特殊的Bash语法定义测试用例
  • 完整的工具链:包含安装、卸载、版本管理脚本
  • 多平台支持:支持各种UNIX系统和架构
  • ShellCheck集成:内置代码质量检查工具
  • 灵活的安装选项:支持自定义安装路径和库目录
  • 版本管理:提供专业的版本发布和更新工具

安装指南

基本安装

# 克隆仓库
git clone https://github.com/bats-core/bats-core.git
cd bats-core

# 安装到系统目录
./install.sh /usr/local

# 或者安装到自定义目录
./install.sh ~/bats

自定义库目录安装

# 指定库目录(如lib64)
./install.sh /usr/local lib64

依赖要求

  • Bash 3.2或更高版本
  • 标准UNIX工具(install, find, sed等)
  • 可选:Ron用于生成手册页

使用说明

创建测试文件

#!/usr/bin/env bats

@test "加法测试 - 使用bc" {
  result="$(echo 2+2 | bc)"
  [ "$result" -eq 4 ]
}

@test "加法测试 - 使用dc" {
  result="$(echo 2 2+p | dc)"
  [ "$result" -eq 4 ]
}

@test "文件存在性测试" {
  run ls /etc/passwd
  [ "$status" -eq 0 ]
  [ "$output" = "/etc/passwd" ]
}

运行测试

# 运行所有测试
bats test/

# 使用TAP格式输出
bats --tap test/

# 运行单个测试文件
bats my_test.bats

测试项目结构

my_project/
├── src/
│   └── my_script.sh
└── test/
    ├── unit/
    │   └── test_basics.bats
    └── integration/
        └── test_complex.bats

核心代码

安装脚本核心逻辑

#!/usr/bin/env bash
set -e

BATS_ROOT="${0%/*}"
PREFIX="${1%/}"
LIBDIR="${2:-lib}"

# 参数验证
if [[ -z "$PREFIX" ]]; then
  printf '%s\n' \
    "usage: $0 <prefix> [base_libdir]" \
    "  e.g. $0 /usr/local" \
    "       $0 /usr/local lib64" >&2
  exit 1
fi

# 创建目录结构
install -d -m 755 "$PREFIX"/{bin,libexec/bats-core,"${LIBDIR}"/bats-core,share/man/man{1,7}}

# 安装文件
install -m 755 "$BATS_ROOT/bin"/* "$PREFIX/bin"
install -m 755 "$BATS_ROOT/libexec/bats-core"/* "$PREFIX/libexec/bats-core"
install -m 755 "$BATS_ROOT/lib/bats-core"/* "$PREFIX/${LIBDIR}/bats-core"
install -m 644 "$BATS_ROOT/man/bats.1" "$PREFIX/share/man/man1"
install -m 644 "$BATS_ROOT/man/bats.7" "$PREFIX/share/man/man7"

# 更新库目录配置
read -rd '' BATS_EXE_CONTENTS <"$PREFIX/bin/bats" || true
BATS_EXE_CONTENTS=${BATS_EXE_CONTENTS/"BATS_BASE_LIBDIR=lib"/"BATS_BASE_LIBDIR=${LIBDIR}"}
printf "%s" "$BATS_EXE_CONTENTS" >| "$PREFIX/bin/bats"

echo "Installed Bats to $PREFIX/bin/bats"

卸载脚本核心逻辑

#!/usr/bin/env bash
set -e

BATS_ROOT="${0%/*}"
PREFIX="${1%/}"

# 参数检查
if [[ -z "$PREFIX" ]]; then
  printf '%s\n' \
    "usage: $0 <prefix> [base_libdir]" \
    "  e.g. $0 /usr/local" \
    "       $0 /usr/local lib64" >&2
  exit 1
fi

# 目录存在性验证
if [[ ! -d "$PREFIX" ]]; then
  printf "No valid installation in directory %s.\n" "$PREFIX"
  exit 2
fi

# 自动检测库目录
if [ -e "$PREFIX/bin/bats" ]; then
  LIBDIR=$(grep -e '^BATS_BASE_LIBDIR=' "$PREFIX/bin/bats")
  eval "$LIBDIR"
fi
LIBDIR="${BATS_BASE_LIBDIR:-lib}"

# 文件删除函数
remove_file() {
  echo "Removing $1"
  rm -f "$1"
}

remove_directory() {
  local directory=$1
  if [[ -d "$directory" ]]; then
    echo "Removing $directory"
    rmdir "$directory"
  fi
}

# 清理安装的文件
d="$PREFIX/bin"
for elt in "$BATS_ROOT/bin"/*; do
  elt=${elt##*/}
  remove_file "$d/$elt"
done

echo "Uninstalled Bats from $PREFIX/bin/bats"

版本发布工具

#!/usr/bin/env bash
set -Eeuo pipefail

# 版本信息提取
BATS_VERSION=$(
  source <(grep '^export BATS_VERSION=' libexec/bats-core/bats)
  echo "${BATS_VERSION}"
)

# 版本更新函数
replace_in_files() {
  declare -a FILE_REPLACEMENTS=(
    "contrib/rpm/bats.spec,^Version:"
    "libexec/bats-core/bats,^export BATS_VERSION="
    "package.json,^  \"version\":"
  )

  for FILE_REPLACEMENT in "${FILE_REPLACEMENTS[@]}"; do
    FILE="${FILE_REPLACEMENT/,*/}"
    MATCH="${FILE_REPLACEMENT/*,/}"
    sed -E -i.bak "/${MATCH}/ { s,${BATS_VERSION},${NEW_BATS_VERSION},g; }" "${FILE}"
    rm "${FILE}.bak" || true
    git add -f "${FILE}"
  done
}

# 更新变更日志
write_changelog() {
  local FILE="docs/CHANGELOG.md"
  sed -E -i.bak "/## \[Unreleased\]/ a \\\n## [${NEW_BATS_VERSION}] - $(date +%Y-%m-%d)" "${FILE}"
  rm "${FILE}.bak" || true
  git add -f "${FILE}"
}

ShellCheck代码质量检查

#!/usr/bin/env bash
set -e

# 查找所有Bash相关文件
targets=()
while IFS= read -r -d $'\0'; do
  targets+=("$REPLY")
done < <(
  find . -type f \( -name \*.bash -o -name \*.sh \) -print0
  find . -type f -name '*.bats' -not -name '*_no_shellcheck*' -print0
  find libexec -type f -print0
  find bin -type f -print0
)

# 执行ShellCheck检查
LC_ALL=C.UTF-8 shellcheck -x "${targets[@]}"

这些核心代码展示了Bats-core项目的完整工具链,包括专业的安装卸载流程、版本管理和代码质量保证机制,体现了项目对测试框架稳定性和可靠性的高度重视。