|
@@ -20,6 +20,179 @@ Shell 脚本的最小测试粒度是单个脚本。必须保证单个脚本是
|
|
|
|
|
|
对于有复杂外部依赖的脚本,可以写脚本自动测试,也可以手动测试,测试时需要包含正常和异常的情况,不能只测试正常情况。
|
|
|
|
|
|
+### 功能测试示例
|
|
|
+
|
|
|
+**需要写脚本完成如下功能:**
|
|
|
+
|
|
|
+如果 process1 和 process2 两个进程都存在,以 process2 进程 cwd 目录中的 `data/output.txt` 为输入,做一些比较复杂的处理,然后输出到 process1 进程 cwd 目录中的 `data/input.txt` 文件(如果该文件已存在,则不处理),处理完后,删除之前的 `data/output.txt`。
|
|
|
+
|
|
|
+**分析:**
|
|
|
+
|
|
|
+process1 和 process2 两个进程都是复杂的外部依赖,不能在主体逻辑脚本里直接依赖它们,所以要把检查进程是否存在的逻辑独立成单独的脚本。输入和输出文件的路径依赖进程路径,为了测试方便,也要把获取文件路径的逻辑独立成单独的脚本。
|
|
|
+
|
|
|
+**脚本功能实现:**
|
|
|
+
|
|
|
+检查进程是否存在和获取进程 cwd 目录的 util.zsh 脚本:
|
|
|
+
|
|
|
+```
|
|
|
+#!/bin/zsh
|
|
|
+
|
|
|
+check_process() {
|
|
|
+ pidof $1
|
|
|
+}
|
|
|
+
|
|
|
+get_process_cwd() {
|
|
|
+ readlink /proc/$1/cwd
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+主体逻辑脚本 main.zsh:
|
|
|
+
|
|
|
+```
|
|
|
+#!/bin/zsh
|
|
|
+
|
|
|
+# 有错误即退出,可以省掉很多错误处理的代码
|
|
|
+set -e
|
|
|
+
|
|
|
+# 切换到脚本当前目录
|
|
|
+cd ${0:h}
|
|
|
+
|
|
|
+# 加载依赖的脚本
|
|
|
+source ./util.zsh
|
|
|
+
|
|
|
+# 检查进程是否存在
|
|
|
+local process1_pid=$(check_process process1)
|
|
|
+local process2_pid=$(check_process process2)
|
|
|
+
|
|
|
+# 这里的 input 和 output 是相对脚本来说的
|
|
|
+local input_file=$(get_process_cwd $process2_pid)/data/output.txt
|
|
|
+local output_file=$(get_process_cwd $process1_pid)/data/input.txt
|
|
|
+
|
|
|
+# 如果输入文件不存在,直接退出
|
|
|
+[[ -e $input_file ]] || {
|
|
|
+ echo $input_file not found.
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+# 如果输出文件已存在,也直接退出
|
|
|
+[[ -e $output_file ]] && {
|
|
|
+ echo $output_file already exists.
|
|
|
+ exit 0
|
|
|
+}
|
|
|
+
|
|
|
+# 处理 $input_file 内容
|
|
|
+# 省略
|
|
|
+
|
|
|
+# 将结果输出到 $output_file
|
|
|
+# 省略
|
|
|
+```
|
|
|
+
|
|
|
+**功能测试方法:**
|
|
|
+
|
|
|
+util.zsh 里的两个函数功能过于简单,无需测试。
|
|
|
+
|
|
|
+测试 main.zsh 时,需要构造一系列测试用的 util.zsh,用于模拟各种情况:
|
|
|
+
|
|
|
+```
|
|
|
+# 进程存在的情况
|
|
|
+check_process() {
|
|
|
+ echo $$
|
|
|
+}
|
|
|
+
|
|
|
+# 进程不存在的情况
|
|
|
+check_process() {
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+# 进程 process1 存在而 process2 不存在的情况
|
|
|
+check_process() {
|
|
|
+ [[ $1 == process1 ]] && echo 1234 && return
|
|
|
+ [[ $1 == process2 ]] && return 1
|
|
|
+}
|
|
|
+
|
|
|
+# 输出了进程号,但实际进程不存在的情况
|
|
|
+check_process() {
|
|
|
+ echo 0
|
|
|
+}
|
|
|
+
|
|
|
+# 路径存在的情况
|
|
|
+get_process_cwd() {
|
|
|
+ [[ $1 == process1 ]] && echo /path/to/cwd1 && return
|
|
|
+ [[ $1 == process2 ]] && echo /path/to/cwd2 && return
|
|
|
+}
|
|
|
+
|
|
|
+# 路径不存在的情况
|
|
|
+get_process_cwd() {
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+# 输出了路径,但路径实际不存在的情况
|
|
|
+get_process_cwd() {
|
|
|
+ echo /wrong/path
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+然后组合这些情况,写测试脚本判断 main.zsh 的处理是否符合预期。
|
|
|
+
|
|
|
+其中一个测试脚本样例:
|
|
|
+
|
|
|
+util_test1.zsh 内容:
|
|
|
+
|
|
|
+```
|
|
|
+#!/bin/zsh
|
|
|
+
|
|
|
+# 进程存在
|
|
|
+check_process() {
|
|
|
+ echo $$
|
|
|
+}
|
|
|
+
|
|
|
+# 直接返回正确的路径
|
|
|
+get_process_cwd() {
|
|
|
+ [[ $1 == process1 ]] && echo /path/to/cwd1 && return
|
|
|
+ [[ $1 == process2 ]] && echo /path/to/cwd2 && return
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+test.zsh 内容:
|
|
|
+
|
|
|
+```
|
|
|
+#!/bin/zsh
|
|
|
+
|
|
|
+# 用于测试的函数,可以独立成单独脚本以便复用
|
|
|
+assert_ok() {
|
|
|
+ (($1 == 0)) || {
|
|
|
+ echo Error, retcode: $1
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+check_output_file() {
|
|
|
+ # 检查输出文件是否符合预期
|
|
|
+ # 省略
|
|
|
+}
|
|
|
+
|
|
|
+# 应用 util_test1.zsh
|
|
|
+ln -sf util_test1.zsh util.zsh
|
|
|
+
|
|
|
+# 运行脚本
|
|
|
+./main.zsh
|
|
|
+
|
|
|
+# 检查返回值是否正常
|
|
|
+assert_ok $?
|
|
|
+
|
|
|
+# 检查输出文件是否符合预期
|
|
|
+check_output_file /path/to/output/file
|
|
|
+
|
|
|
+# 其他检查
|
|
|
+# 省略
|
|
|
+
|
|
|
+# 应用 util_test2.zsh
|
|
|
+ln -sf util_test2.zsh util.zsh
|
|
|
+
|
|
|
+# 省略
|
|
|
+```
|
|
|
+
|
|
|
### 集成测试
|
|
|
|
|
|
测试完每个脚本的功能后,需要将各个脚本以及其他程序整合起来测试互相调用过程是否正常。如果功能比较复杂,需要分批整合,测试各个逻辑单元是否能正常工作。在这部分测试中,和外部环境交互的脚本如果逻辑较为简单,可以不参与,用模拟脚本替代。可以手动测试或自动测试。同样不能只测试正常情况。
|
|
@@ -30,4 +203,4 @@ Shell 脚本的最小测试粒度是单个脚本。必须保证单个脚本是
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
-本文简单介绍了 shell 脚本的测试方法,以及编写可测试代码的方法。更多细节需要后续补充。
|
|
|
+本文简单介绍了 shell 脚本的测试方法,以及编写可测试代码的方法。
|