命令行critic.sh测试框架与代码覆盖率分析深度解析
《critic.sh:Bash测试框架与代码覆盖率实践》 摘要: critic.sh是一个轻量级Bash测试框架,支持测试套件定义、断言验证和代码覆盖率分析。本文档详细介绍了该工具的安装方法(支持tar.gz包和手动安装两种方式)、基础语法(包括测试套件定义、断言函数使用)以及实际应用场景(函数测试、命令行工具测试等)。特别展示了其核心功能——通过LCOV和HTML格式生成代码覆盖率报告,帮助开发
critic.sh 是一个简单易用的 Bash 测试框架,支持代码覆盖率报告。本文档全面介绍 critic.sh 的测试方法论、API 设计、覆盖率分析技巧和工程实践,帮助开发者构建高质量、可维护的 Bash 脚本测试体系。
📋 目录
一、快速开始
1.1 安装 critic.sh
方式一:使用 tar.gz 包安装
# 在鸿蒙PC上执行
tar -xzf ohos_critic.sh_0.1.1.tar.gz
cp -r critic.sh_0.1.1/* /data/service/hnp/critic.sh.org/critic.sh_0.1.1/
方式二:手动安装
# 复制文件到安装目录
mkdir -p /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin
cp bin/critic.sh /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/
cp bin/critic /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/
chmod +x /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/*
# 添加到 PATH
export PATH=$PATH:/data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin
1.2 验证安装
# 使用 critic 命令(推荐)
critic --help
# 或直接使用 bash 执行
bash /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/critic.sh --help
1.3 第一个测试
创建测试脚本 test_example.sh:
#!/usr/bin/env bash
# 包含被测试的源文件
source examples/lib.sh
# 包含测试框架
source critic.sh
# 编写测试套件
_describe foo
_test "output should equal foo"
_assert _output_equals "foo"
_test "return code should be 0"
_assert _return_true "Exit code should be 0"
运行测试:
critic test_example.sh

二、基本语法
2.1 测试套件
定义测试套件
_describe "suite name"
# 测试用例
跳过测试套件
_describe_skip "skipped suite"
# 这些测试会被跳过
2.2 测试用例
定义测试用例
_test "test description"
# 测试代码
_assert _return_true
跳过测试用例
_test_skip "skipped test"
# 这个测试会被跳过
2.3 断言函数
critic.sh 提供以下断言函数:
| 断言函数 | 说明 |
|---|---|
_return_true |
验证返回码为 0 |
_return_false |
验证返回码不为 0 |
_return_equals N |
验证返回码等于 N |
_output_equals TEXT |
验证输出等于 TEXT |
_output_contains TEXT |
验证输出包含 TEXT |
_nth_arg_equals N TEXT |
验证第 N 个参数等于 TEXT |
_not |
取反操作符 |
2.4 自定义断言
# 使用自定义表达式作为断言
_test "custom assertion" "[ 1 -eq 1 ]"
_assert "[ 1 -eq 1 ]"
_assert "[ 2 -eq 2 ]" "Two should be equal to two"
三、使用示例
3.1 基本测试
创建测试脚本 test_basic.sh:
#!/usr/bin/env bash
source critic.sh
# 测试函数 foo
foo() {
echo "foo"
}
_describe foo
_test "output should equal foo"
foo
_assert _output_equals "foo"
_test "return code should be 0"
foo
_assert _return_true "Exit code should be 0"
运行测试:
critic test_basic.sh
输出:
[critic] Running tests in test_basic.sh
foo
output should equal foo
PASS ✔ : Output equals 'foo'
return code should be 0
PASS ✔ : Exit code is 0
[critic] Tests completed. Passed: 2, Failed: 0

3.2 测试库函数
创建库文件 lib.sh:
#!/usr/bin/env bash
add() {
echo $(($1 + $2))
}
multiply() {
echo $(($1 * $2))
}
创建测试文件 test_lib.sh:
#!/usr/bin/env bash
source lib.sh
source critic.sh
_describe "math functions"
_test "add should return sum"
result=$(add 2 3)
_assert _output_equals "5"
_test "multiply should return product"
result=$(multiply 2 3)
_assert _output_equals "6"
运行测试:
critic test_lib.sh
3.3 测试命令行工具
创建测试脚本 test_command.sh:
#!/usr/bin/env bash
source critic.sh
_describe "echo command"
_test "should output text"
echo "hello"
_assert _output_equals "hello"
_describe "grep command"
_test "should find pattern"
echo "hello world" | grep "world"
_assert _return_true
运行测试:
critic test_command.sh
3.4 测试文件操作
创建测试脚本 test_file.sh:
#!/usr/bin/env bash
source critic.sh
_describe "file operations"
_test "should create file"
echo "test" > /tmp/test_file.txt
_assert _return_true
_assert "[ -f /tmp/test_file.txt ]"
_test "should read file"
content=$(cat /tmp/test_file.txt)
_assert _output_equals "test"
_test "should delete file"
rm /tmp/test_file.txt
_assert _return_true
_assert "[ ! -f /tmp/test_file.txt ]"
运行测试:
critic test_file.sh
四、高级功能
4.1 代码覆盖率报告
生成 LCOV 格式报告
# 运行测试并生成覆盖率报告
critic test_example.sh
# 覆盖率报告会保存在 coverage/ 目录
ls coverage/
# lcov.info
生成 HTML 覆盖率报告
# 设置环境变量启用 HTML 报告
export CRITIC_COVERAGE_REPORT_HTML=true
critic test_example.sh
# HTML 报告会保存在 coverage/report/ 目录
覆盖率报告示例:
[critic] Coverage Report
/path/to/examples/lib.sh
Total LOC: 19
Covered LOC: 3
Coverage %: 50
Ignored LOC: 5
Uncovered Lines: 21 22 30
4.2 测试跳过
跳过整个测试套件
_describe_skip "skipped suite"
_test "this test will be skipped"
_assert _return_true
跳过单个测试
_describe "normal suite"
_test_skip "this test will be skipped"
_assert _return_true
4.3 清理函数
使用 _teardown 在测试后清理:
_describe "test with cleanup"
_test "should create temp file"
echo "test" > /tmp/test_temp.txt
_assert _return_true
_teardown
rm -f /tmp/test_temp.txt
4.4 自定义断言消息
_test "custom assertion message"
result=$(add 2 3)
_assert "[ $result -eq 5 ]" "Result should be 5, got $result"
五、实际应用场景
5.1 系统脚本测试
测试系统管理脚本:
#!/usr/bin/env bash
source backup.sh
source critic.sh
_describe "backup script"
_test "should create backup archive"
backup_script /tmp/data
_assert _return_true
_assert "[ -f /tmp/data/backup.tar.gz ]"
_test "should restore from backup"
restore_script /tmp/data/backup.tar.gz /tmp/restored
_assert _return_true
_assert "[ -d /tmp/restored ]"
5.2 工具链测试
测试编译工具、构建工具等:
#!/usr/bin/env bash
source critic.sh
_describe "compiler test"
_test "should compile C program"
echo 'int main(){return 0;}' > test.c
clang test.c -o test
_assert _return_true
./test
_assert _return_true
_test "should handle compilation errors"
echo 'int main(){return' > test_error.c
clang test_error.c -o test_error 2>&1
_assert _return_false
5.3 配置文件验证
验证配置文件格式、内容等:
#!/usr/bin/env bash
source critic.sh
_describe "config validation"
_test "should validate config syntax"
echo "key=value" > config.conf
grep -q "key=value" config.conf
_assert _return_true
_test "should detect invalid config"
echo "invalid" > config.conf
validate_config config.conf 2>&1
_assert _return_false
5.4 API 测试
测试 REST API 或命令行 API:
#!/usr/bin/env bash
source critic.sh
_describe "API test"
_test "should return 200 status"
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api)
_assert _output_equals "200"
_test "should return JSON data"
response=$(curl -s http://localhost:8080/api/data)
echo "$response" | grep -q "success"
_assert _return_true
六、常见问题
6.1 Bash 版本问题
问题:critic.sh 需要 Bash 4.1+。
解决:确保系统已安装 Bash 4.1 或更高版本:
bash --version
# 应该显示 4.1 或更高版本
6.2 覆盖率报告不生成
问题:覆盖率报告没有生成。
解决:
- 确保使用 Bash 4.1+
- 检查环境变量设置
- 确保测试脚本正确 source 了被测试的文件
# 启用覆盖率追踪
export CRITIC_COVERAGE_ENABLE=1
critic test.sh
6.3 测试失败但无错误信息
问题:测试失败但没有详细的错误信息。
解决:使用自定义断言消息:
_test "should return expected value"
result=$(my_function)
_assert "[ $result -eq 42 ]" "Expected 42, got $result"
6.4 路径问题
问题:测试脚本找不到被测试的文件。
解决:使用绝对路径或设置工作目录:
# 使用绝对路径
source /path/to/lib.sh
# 或设置工作目录
cd /path/to/project
source lib.sh
6.5 环境变量问题
问题:测试需要特定的环境变量。
解决:在测试中设置环境变量:
_test "should use environment variable"
export MY_VAR=test_value
result=$(my_function)
_assert _output_equals "test_value"
七、最佳实践
7.1 测试组织
- 每个测试文件测试一个模块或功能
- 使用描述性的测试套件名称
- 保持测试独立,不依赖其他测试
7.2 断言使用
- 使用最具体的断言函数
- 为自定义断言提供清晰的错误消息
- 避免过度使用
_not操作符
7.3 覆盖率目标
- 为目标代码设置合理的覆盖率目标
- 关注关键路径的覆盖率
- 定期查看覆盖率报告,发现未测试的代码
7.4 CI/CD 集成
#!/bin/bash
# CI/CD 测试脚本
# 运行所有测试
for test_file in tests/*.sh; do
critic "$test_file" || exit 1
done
# 检查覆盖率
if [ -f coverage/lcov.info ]; then
coverage=$(grep -oP '^LF:\K\d+' coverage/lcov.info | head -1)
echo "Coverage: $coverage%"
fi
八、总结
critic.sh 是一个功能强大且易用的 Bash 测试框架,通过简洁的 API 就能实现完整的测试功能。主要优势:
- 简单易用:API 设计直观,学习成本低
- 功能完整:支持测试、断言、覆盖率等完整功能
- 代码覆盖率:提供 LCOV 格式的覆盖率报告
- 灵活扩展:支持自定义断言和表达式
通过本教程,您应该能够:
- ✅ 安装和配置 critic.sh
- ✅ 编写各种类型的测试
- ✅ 使用代码覆盖率功能
- ✅ 在实际项目中应用 critic.sh
更多推荐


所有评论(0)