uCOS-III内核源码深度解析与STM32移植实战指南
2026/9/8 1:24:38
critic.sh是一个简单易用的 Bash 测试框架,支持代码覆盖率报告。本文档全面介绍 critic.sh 的测试方法论、API 设计、覆盖率分析技巧和工程实践,帮助开发者构建高质量、可维护的 Bash 脚本测试体系。
# 在鸿蒙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/bin# 使用 critic 命令(推荐)critic --help# 或直接使用 bash 执行bash/data/service/hnp/critic.sh.org/critic.sh_0.1.1/bin/critic.sh --help创建测试脚本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_describe"suite name"# 测试用例_describe_skip"skipped suite"# 这些测试会被跳过_test"test description"# 测试代码_assert _return_true_test_skip"skipped test"# 这个测试会被跳过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 | 取反操作符 |
# 使用自定义表达式作为断言_test"custom assertion""[ 1 -eq 1 ]"_assert"[ 1 -eq 1 ]"_assert"[ 2 -eq 2 ]""Two should be equal to two"创建测试脚本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: 0创建库文件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.sh创建测试脚本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.sh创建测试脚本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# 运行测试并生成覆盖率报告critic test_example.sh# 覆盖率报告会保存在 coverage/ 目录lscoverage/# lcov.info# 设置环境变量启用 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 30_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使用_teardown在测试后清理:
_describe"test with cleanup"_test"should create temp file"echo"test">/tmp/test_temp.txt _assert _return_true _teardownrm-f /tmp/test_temp.txt_test"custom assertion message"result=$(add23)_assert"[$result-eq 5 ]""Result should be 5, got$result"测试系统管理脚本:
#!/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 ]"测试编译工具、构建工具等:
#!/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_false验证配置文件格式、内容等:
#!/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_false测试 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问题:critic.sh需要 Bash 4.1+。
解决:确保系统已安装 Bash 4.1 或更高版本:
bash--version# 应该显示 4.1 或更高版本问题:覆盖率报告没有生成。
解决:
# 启用覆盖率追踪exportCRITIC_COVERAGE_ENABLE=1critic test.sh问题:测试失败但没有详细的错误信息。
解决:使用自定义断言消息:
_test"should return expected value"result=$(my_function)_assert"[$result-eq 42 ]""Expected 42, got$result"问题:测试脚本找不到被测试的文件。
解决:使用绝对路径或设置工作目录:
# 使用绝对路径source/path/to/lib.sh# 或设置工作目录cd/path/to/projectsourcelib.sh问题:测试需要特定的环境变量。
解决:在测试中设置环境变量:
_test"should use environment variable"exportMY_VAR=test_valueresult=$(my_function)_assert _output_equals"test_value"_not操作符#!/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%"ficritic.sh 是一个功能强大且易用的 Bash 测试框架,通过简洁的 API 就能实现完整的测试功能。主要优势:
通过本教程,您应该能够: