1. shell 功能测试
1.1 实验目的
利用 C++ 单元测试框架 googletest 的特性,对 Minishell 项目进行系统性的黑盒测试。
1.2 Minishell 项目介绍
Minishell 是一个简化版的 Unix Shell 实现,支持以下功能:
基础命令执行
- 可以执行绝对路径、相对路径或通过环境变量 PATH 查找的可执行文件(如
/bin/ls或ls) - 支持命令参数和选项
- 支持单引号
'和双引号"的字符串解析(不支持多行命令)
命令分隔与重定向
- 使用
;分隔多个命令 - 支持输出重定向
>和追加重定向>> - 支持输入重定向
< - 支持管道
|
环境变量与特殊变量
- 支持环境变量如
$HOME、$PATH等 - 支持特殊变量
$?(上一条命令的返回值)
信号处理
Ctrl-C中断当前程序Ctrl-\退出当前程序Ctrl-D发送 EOF
内置命令(Built-in)
echo:输出文本,支持-n选项pwd:显示当前工作目录cd:切换目录env:显示环境变量export:设置环境变量unset:删除环境变量exit:退出 shell
1.3 环境配置
本实验需要在 Linux 或 macOS 环境下进行(Windows 用户可使用 WSL)。推荐使用 VSCode 作为代码编辑器,并安装以下插件:
- C/C++ Extension Pack
- Python Extension Pack
然后,为了正确编译并使用 gtest 测试 Minishell,你将需要:
- 支持 C++14 及以上的 C++ 编译器
- 构建工具 CMake 和 Make
- Minishell 项目的编译依赖
配置测试环境
对于 Linux 平台,编译器使用 Clang,通过包管理器安装。以 Debian/Ubuntu 为例:
sudo apt install gcc g++ cmake make clang
对于 Mac 平台,我们同样推荐使用包管理器 Homebrew 配置环境。在 Mac 终端内输入
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
以安装 Homebrew。随后安装所需软件:
brew install gcc g++ cmake make clang
为验证构建工具已正确安装,在终端输入
cmake --version
make --version
clang --version
若正确显示版本信息,表示工具已经安装并准备好使用。
编译 Minishell
在项目根目录下进入 source/minishell 目录:
cd source/minishell
make
编译成功后,会在当前目录生成 minishell 可执行文件。你可以手动测试:
./minishell
minishell$ echo "Hello World"
Hello World
minishell$ exit
1.4 GoogleTest 测试框架介绍
在 GoogleTest 中,定义了多种宏来编写测试。针对本实验的 Minishell 测试,我们将重点使用以下功能:
TEST 宏
TEST(TestSuiteName, TestName) {
... statements ...
}
在测试套件 TestSuiteName 中定义一个名为 TestName 的测试。
TEST_F 宏(测试夹具)
TEST_F(TestFixtureName, TestName) {
... statements ...
}
定义一个使用测试夹具类 TestFixtureName 的测试。测试夹具用于:
- 在每个测试前进行初始化(如启动 minishell 进程)
- 在每个测试后进行清理(如关闭进程、删除临时文件)
- 复用测试代码,减少重复
TEST_P 宏(参数化测试)
TEST_P(TestFixtureName, TestName) {
... statements ...
}
定义一个值参数化测试,使用测试夹具类 TestFixtureName。参数化测试的优势:
- 减少重复代码:相同的测试逻辑可以应用于不同的输入数据
- 提高测试覆盖率:轻松测试大量输入组合
- 便于维护:修改测试逻辑时只需改一处
参数化测试特别适合测试 Shell 命令,因为:
- 同一个命令可能有多种输入组合(参数、选项、边界值)
- 可以系统性地测试等价类和边界值
- 便于实施黑盒测试方法
INSTANTIATE_TEST_SUITE_P 宏
INSTANTIATE_TEST_SUITE_P(InstantiationName,
TestSuiteName,
param_generator)
实例化参数化测试套件,其中 param_generator 可以是:
Values(v1, v2, v3, ...): 显式指定参数值ValuesIn(container): 从容器中读取参数Range(begin, end, step): 生成范围内的参数Combine(g1, g2, ...): 组合多个参数生成器(笛卡尔积)
断言宏
GoogleTest 提供了丰富的断言宏用于验证测试结果:
基本断言:
EXPECT_TRUE(condition): 期望条件为真EXPECT_FALSE(condition): 期望条件为假EXPECT_EQ(val1, val2): 期望两个值相等EXPECT_NE(val1, val2): 期望两个值不相等
EXPECT vs ASSERT:
EXPECT_*: 失败时记录错误,继续执行后续测试ASSERT_*: 失败时立即终止当前测试用例
更多断言宏可参考 GoogleTest 官方文档。
1.5 实验内容
本实验将对 Minishell 的各项功能进行系统性测试,综合运用等价类划分、边界值分析等黑盒测试方法,并使用参数化测试提高测试效率。实验所需文件结构如下:
unittest-cpp/
├── CMakeLists.txt # CMake 构建配置
├── minishell_test_base.h # 测试基类(提供辅助函数)
├── minishell_builtin_test.cc # 内置命令测试(等价类划分)
├── minishell_redirect_test.cc # 重定向功能测试(组合测试)
└── minishell_pipe_test.cc # 管道功能测试(决策表测试)
已在 unittest-cpp/minishell_test_base.h 提供了一个测试辅助类来与 Minishell 进程交互,只需修改三个 .cc 文件即可。
1.5.1 内置命令测试
测试目标:在 unittest-cpp/minishell_builtin_test.cc 测试各内置部分命令功能是否正常。
实验要求:
- 完成所有标记为
TODO的测试用例 - 为
echo命令至少添加 5 个参数化测试用例,覆盖不同的等价类。输入类型等价类可细分为:- 有效等价类:
- EC1: 普通字符串(无特殊字符)
- EC2: 包含空格的字符串
- EC3: 空字符串
- EC4: 包含环境变量的字符串
- EC5: 包含特殊字符的字符串(需要引号)
- 无效等价类:
- EC6: 未定义的环境变量
- 有效等价类:
- 为
cd命令完成边界值测试,至少包含 5 个测试点
编译运行:
cd unittest-cpp
cmake -S . -B build
cmake --build build
cd build && ctest --verbose
1.5.2 重定向功能测试
测试目标: unittest-cpp/minishell_redirect_test.cc 测试输入/输出重定向功能(>, >>, <)。
实验要求:
- 完成所有
TODO标记的函数 - 使用
Combine()或Values()创建至少 6 个组合测试用例
1.5.3 管道功能测试(决策表测试)
测试目标:测试管道 | 功能以及管道与其他功能的组合
决策表分析:
管道功能涉及多个条件的组合:
| 条件 | C1: 命令1有效 | C2: 命令2有效 | C3: 有重定向 | 预期结果 |
|---|---|---|---|---|
| R1 | Y | Y | N | 成功 |
| R2 | Y | Y | Y | 成功 |
| R3 | Y | N | N | 失败 |
| R4 | N | Y | N | 失败 |
实验要求:
- 完成所有
TODO标记的测试 - 根据决策表实现至少 4 个测试规则
编译运行:
cd unittest-cpp
cmake -S . -B build
cmake --build build
cd build && ctest --verbose
Acknowledgement
cclaude42. Minishell: 42 - rewrite a simple shell. https://github.com/cclaude42/minishell