使用shUnit2编写Shell单元测试时出现‘command not found’错误求助
问题排查:shUnit2测试脚本报错
testScriptExecution: command not found 我写了一个能自动提取两次Git提交间文件变更并保存到指定目录的Shell脚本,带有日志与错误处理机制。现在为它编写带数据模拟的单元测试,但运行test_extract_delta.sh时出现如下错误:
$ ./test_extract_delta.sh testScriptExecution ../../shunit2/shunit2/shunit2: line 1125: testScriptExecution: command not found shunit2:ERROR testScriptExecution() returned non-zero return code. Ran 1 test.
我的单元测试代码如下:
#!/usr/bin/env sh # Load shUnit2 . ../../shunit2/shunit2/shunit2 # Setup mock environment setUp() { # Mocking environment variables export EXTRACT_DELTA_CONSOLE_LOG_PATH=\"/tmp/extract_delta_console_log\" export MINIMIZED_CHECKOUT_ROOT=\"/tmp/minimized_checkout_root\" export MINIMIZED_CHECKOUT_REF=\"mock_ref\" export CHECKOUT_ROOT=\"/tmp/checkout_root\" export CHECKOUT_REF=\"mock_checkout_ref\" export TO_REVISION=\"mock_to_revision\" export FROM_REVISION=\"mock_from_revision\" export EXTRACTED_DELTA_ROOT=\"/tmp/extracted_delta_root\" export POD_NAME=\"mock_pod_name\" export RESULTS_FROM_COMMIT_PATH=\"/tmp/results_from_commit_path\" export RESULTS_TO_COMMIT_PATH=\"/tmp/results_to_commit_path\" export RESULTS_EXTRACTED_DELTA_REF_PATH=\"/tmp/results_extracted_delta_ref_path\" # Create necessary directories mkdir -p $EXTRACT_DELTA_CONSOLE_LOG_PATH mkdir -p $MINIMIZED_CHECKOUT_ROOT/$MINIMIZED_CHECKOUT_REF mkdir -p $CHECKOUT_ROOT/$CHECKOUT_REF mkdir -p $EXTRACTED_DELTA_ROOT/$POD_NAME # Mock git commands mock_git_rev_parse() { case \"$1\" in mock_from_revision) echo \"mock_from_sha\" ;; mock_to_revision) echo \"mock_to_sha\" ;; esac } mock_git_diff() { echo \"file1.txt\" echo \"file2.txt\" echo \"file3.txt\" } # Mock commands by overriding with functions git() { if [ \"$1\" = \"rev-parse\" ]; then mock_git_rev_parse \"$2\" elif [ \"$1\" = \"diff\" ]; then mock_git_diff \"$@\" fi } # Create mock files touch \"$CHECKOUT_ROOT/$CHECKOUT_REF/file1.txt\" touch \"$CHECKOUT_ROOT/$CHECKOUT_REF/file2.txt\" touch \"$CHECKOUT_ROOT/$CHECKOUT_REF/file3.txt\" # Create minimized checkout mock files touch \"$MINIMIZED_CHECKOUT_ROOT/$MINIMIZED_CHECKOUT_REF/file1.txt\" touch \"$MINIMIZED_CHECKOUT_ROOT/$MINIMIZED_CHECKOUT_REF/file3.txt\" } # Teardown mock environment tearDown() { rm -rf /tmp/extract_delta_console_log rm -rf /tmp/minimized_checkout_root rm -rf /tmp/checkout_root rm -rf /tmp/extracted_delta_root rm -rf /tmp/results_from_commit_path rm -rf /tmp/results_to_commit_path rm -rf /tmp/results_extracted_delta_ref_path } # Test case: Run the script and verify outcomes testScriptExecution() { # Run the script . ../scripts/extract-delta.sh # Check that files were copied correctly assertTrue \"file1.txt should exist in extracted delta path\" \"[ -f $EXTRACTED_DELTA_ROOT/$POD_NAME/file1.txt ]\" assertTrue \"file3.txt should exist in extracted delta path\" \"[ -f $EXTRACTED_DELTA_ROOT/$POD_NAME/file3.txt ]\" assertFalse \"file2.txt should not exist in extracted delta path\" \"[ -f $EXTRACTED_DELTA_ROOT/$POD_NAME/file2.txt ]\" # Check that commit SHAs were written to the correct paths assertEquals \"mock_from_sha\" \"$(cat $RESULTS_FROM_COMMIT_PATH)\" assertEquals \"mock_to_sha\" \"$(cat $RESULTS_TO_COMMIT_PATH)\" # Check that the POD_NAME was written to the correct path assertEquals \"mock_pod_name\" \"$(cat $RESULTS_EXTRACTED_DELTA_REF_PATH)\" } # Load and run shunit2 . ../../shunit2/shunit2/shunit2
问题根源
重复加载shUnit2导致测试函数丢失
脚本开头和结尾各加载了一次../../shunit2/shunit2/shunit2。第一次加载时shUnit2会扫描并注册testScriptExecution等测试函数,但第二次加载会重置shUnit2内部状态,覆盖之前的注册信息,导致执行时找不到测试函数。环境变量赋值的多余转义引号
setUp中给环境变量赋值时使用了转义引号(如=\"/tmp/...\"),这会让变量值包含引号本身,后续创建目录、操作文件时会因为路径带引号而失效。mock函数的作用域问题
mock_git_rev_parse和mock_git_diff定义在setUp内部,Shell中函数内的子函数作用域受限,外部的git函数调用它们时可能找不到,导致mock失效。
修复方案
1. 移除重复的shUnit2加载
删掉脚本开头的../../shunit2/shunit2/shunit2加载语句,只保留末尾的加载执行逻辑。
2. 去掉环境变量的多余转义引号
将setUp中的环境变量赋值改为正常格式:
export EXTRACT_DELTA_CONSOLE_LOG_PATH="/tmp/extract_delta_console_log" export MINIMIZED_CHECKOUT_ROOT="/tmp/minimized_checkout_root" # 其他变量同理,去掉转义的\",直接使用双引号或无引号(路径无空格时)
3. 调整mock函数作用域
把mock_git_rev_parse和mock_git_diff移到setUp外部,确保git函数能正常调用它们:
# 把mock函数移到setUp外面 mock_git_rev_parse() { case "$1" in mock_from_revision) echo "mock_from_sha" ;; mock_to_revision) echo "mock_to_sha" ;; esac } mock_git_diff() { echo "file1.txt" echo "file2.txt" echo "file3.txt" } setUp() { # ...其他代码不变 git() { if [ "$1" = "rev-parse" ]; then mock_git_rev_parse "$2" elif [ "$1" = "diff" ]; then mock_git_diff "$@" fi } # ...其他代码不变 }
4. 可选:确保测试脚本有执行权限
如果还没设置执行权限,运行以下命令:
chmod +x test_extract_delta.sh
内容的提问来源于stack exchange,提问作者Ruwi
相关产品推荐
相关产品推荐

