critic.sh是一个简单易用的 Bash 测试框架,支持代码覆盖率报告。本文档全面介绍 critic.sh 的测试方法论、API 设计、覆盖率分析技巧和工程实践,帮助开发者构建高质量、可维护的 Bash 脚本测试体系。
📋 目录
- 一、快速开始
- 二、基本语法
- 三、使用示例
- 四、高级功能
- 五、实际应用场景
- 六、常见问题
一、快速开始
1.1 安装 critic.sh
方式一:使用 tar.gz 包安装
# 在鸿蒙PC上执行tar-xzf ohos_critic.sh_0.1.1.tar.gzcp-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/bincpbin/critic.sh /data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/cpbin/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/*# 添加到 PATHexportPATH=$PATH:/data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin1.2 验证安装
# 使用 critic 命令(推荐)critic --help# 或直接使用 bash 执行bash/data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/critic.sh --help1.3 第一个测试
创建测试脚本test_example.sh:
#!/usr/bin/env bash# 包含被测试的源文件sourceexamples/lib.sh# 包含测试框架sourcecritic.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 bashsourcecritic.sh# 测试函数 foofoo(){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: 03.2 测试库函数
创建库文件lib.sh:
#!/usr/bin/env bashadd(){echo$(($1+$2))}multiply(){echo$(($1*$2))}创建测试文件test_lib.sh:
#!/usr/bin/env bashsourcelib.shsourcecritic.sh _describe"math functions"_test"add should return sum"result=$(add23)_assert _output_equals"5"_test"multiply should return product"result=$(multiply23)_assert _output_equals"6"运行测试:
critic test_lib.sh3.3 测试命令行工具
创建测试脚本test_command.sh:
#!/usr/bin/env bashsourcecritic.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.sh3.4 测试文件操作
创建测试脚本test_file.sh:
#!/usr/bin/env bashsourcecritic.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/ 目录lscoverage/# lcov.info生成 HTML 覆盖率报告
# 设置环境变量启用 HTML 报告exportCRITIC_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 304.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_true4.3 清理函数
使用_teardown在测试后清理:
_describe"test with cleanup"_test"should create temp file"echo"test">/tmp/test_temp.txt _assert _return_true _teardownrm-f /tmp/test_temp.txt4.4 自定义断言消息
_test"custom assertion message"result=$(add23)_assert"[$result-eq 5 ]""Result should be 5, got$result"五、实际应用场景
5.1 系统脚本测试
测试系统管理脚本:
#!/usr/bin/env bashsourcebackup.shsourcecritic.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 bashsourcecritic.sh _describe"compiler test"_test"should compile C program"echo'int main(){return 0;}'>test.c clang test.c -otest_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_error2>&1_assert _return_false5.3 配置文件验证
验证配置文件格式、内容等:
#!/usr/bin/env bashsourcecritic.sh _describe"config validation"_test"should validate config syntax"echo"key=value">config.confgrep-q"key=value"config.conf _assert _return_true _test"should detect invalid config"echo"invalid">config.conf validate_config config.conf2>&1_assert _return_false5.4 API 测试
测试 REST API 或命令行 API:
#!/usr/bin/env bashsourcecritic.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 了被测试的文件
# 启用覆盖率追踪exportCRITIC_COVERAGE_ENABLE=1critic test.sh6.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/projectsourcelib.sh6.5 环境变量问题
问题:测试需要特定的环境变量。
解决:在测试中设置环境变量:
_test"should use environment variable"exportMY_VAR=test_valueresult=$(my_function)_assert _output_equals"test_value"七、最佳实践
7.1 测试组织
- 每个测试文件测试一个模块或功能
- 使用描述性的测试套件名称
- 保持测试独立,不依赖其他测试
7.2 断言使用
- 使用最具体的断言函数
- 为自定义断言提供清晰的错误消息
- 避免过度使用
_not操作符
7.3 覆盖率目标
- 为目标代码设置合理的覆盖率目标
- 关注关键路径的覆盖率
- 定期查看覆盖率报告,发现未测试的代码
7.4 CI/CD 集成
#!/bin/bash# CI/CD 测试脚本# 运行所有测试fortest_fileintests/*.sh;docritic"$test_file"||exit1done# 检查覆盖率if[-f coverage/lcov.info];thencoverage=$(grep-oP'^LF:\K\d+'coverage/lcov.info|head-1)echo"Coverage:$coverage%"fi八、总结
critic.sh 是一个功能强大且易用的 Bash 测试框架,通过简洁的 API 就能实现完整的测试功能。主要优势:
- 简单易用:API 设计直观,学习成本低
- 功能完整:支持测试、断言、覆盖率等完整功能
- 代码覆盖率:提供 LCOV 格式的覆盖率报告
- 灵活扩展:支持自定义断言和表达式
通过本教程,您应该能够:
- ✅ 安装和配置 critic.sh
- ✅ 编写各种类型的测试
- ✅ 使用代码覆盖率功能
- ✅ 在实际项目中应用 critic.sh