运行测试
VSAG 采用 Catch2 作为测试框架,测试分为两类:
- 单元测试:与源码同目录,位于
src/下,聚焦单个类/函数的行为。 - 功能测试:位于
tests/目录,覆盖跨模块、端到端的索引行为。典型用例包括test_hgraph.cpp、test_ivf.cpp、test_pyramid.cpp、test_sindi.cpp、test_brute_force.cpp、test_memleak.cpp等。
构建并运行全部测试
make test 会以 Debug 配置重新编译(启用 ENABLE_TESTS=ON)并运行单元与功能测试:
make test
构建并运行单个单元测试模块
为了缩短编辑、构建和测试周期,可以只构建并运行一个仍在维护的单元测试子系统:
make test-module MODULE=datacell
make test-module MODULE=algorithm CASE='[ut][sample_train_data]'
可用模块名为 simd、common、algorithm、factory、attr、datacell、layout、
quantization、storage、io、utils 和 impl。每条命令都会构建共享的生产代码与测试夹具依赖,
但只编译所选模块的测试源码。对应的 CMake 目标和可执行文件名为 unittests_<module>:
cmake -S . -B build -DENABLE_TESTS=ON
cmake --build build --target unittests_datacell
./build/tests/unittests_datacell '[ut][AttributeInvertedInterfaceParameter]'
模块目标仅用于加速本地开发。完整验证仍应运行 make test;其中聚合的 unittests 可执行文件包含所有模块。
说明:
- 运行
src/下的单元测试; - 运行
tests/下的功能测试; make test并未开启覆盖率(ENABLE_COVERAGE=ON)。需要覆盖率报告时请使用make cov:该目标仅完成带覆盖率插桩的编译,随后按下文命令以固定随机种子运行 与覆盖率 CI 相同的非 daily 单元测试和功能测试并生成报告。
仅运行单个测试二进制
构建完成后,可直接运行单个测试:
./build/tests/functests "[hgraph]"
./build/tests/functests "[hgraph][concurrent]"
Catch2 支持按名字、tag、通配符等方式筛选用例,详见 --help。
覆盖率
贡献时应保持 src/ 与 include/ 下代码的行覆盖率不低于 90%。在本地执行:
make cov
VSAG_TEST_SEED=424242 bash scripts/testing/test_parallel_bg.sh
bash scripts/coverage/collect_cpp_coverage.sh
bash scripts/coverage/check_cov.sh
采集脚本会生成包含分支数据和仓库相对路径的 coverage/coverage.info。统计范围仅包括
src/ 下的维护中生产代码和 include/ 下的公共头文件,并排除 src/ 下的
version.h(构建时由 cmake/GenerateVersionHeader.cmake 从纳入版本控制的模板
src/version.h.in 生成)与引入的兼容头文件 include/vsag/expected.hpp。仅在其他平台编译的路径
明确不属于 Linux x86 报告的统计范围,必须由平台专用覆盖率任务统计,不能视为已覆盖。
合并前的 SIMD 覆盖率阶段
PR SIMD Coverage 仅在目标分支为 main 的 PR 修改 SIMD 源码、测试或其构建与覆盖率基础设施时运行。
本阶段有意仅在 main 推出。发布分支保留现有的 PR CI,但不包含这项新的 SIMD 覆盖率检查;扩展到发布分支需要单独推进。
任务在同一台 Linux x86 运行器上依次构建 PR 的基准版本和 GitHub 合并候选版本,
使用四个并行构建任务、OpenBLAS、[simd]~[!benchmark] 测试筛选条件、
Catch2 随机种子 424242 和字典序执行顺序。每次测试限时 15 分钟,整个任务限时 90 分钟。
此阶段仍需构建聚合测试可执行文件。合并后及手动触发的完整单元测试与功能测试覆盖率流程保持不变。
Actions 摘要和产物仅报告维护中的 src/simd/ 代码行覆盖率。
纳入测量的新增可执行代码行覆盖率必须达到 80%;该范围的行覆盖率不得低于本次重新测量的基准,
比较时使用未经四舍五入的比例。新文件计入候选版本及补丁的总量,不虚构文件级基准。
覆盖率数据缺失、SHA 或测试配置不匹配、变更文件未被测量,或未删除源码的记录消失,都会导致失败。
没有测量到新增可执行代码行时,结果为 N/A,而不是 100%。
这是范围有限的第一阶段,尚未提供全项目覆盖率回退保护。任务运行时会列出其他已变更但不受支持的 C++ 路径;
未涉及触发路径的 PR 不会获得此项测量。条件编译路径仍受运行器平台限制。部分测试使用 random_device,
因此 Catch2 种子无法控制所有输入。局部覆盖率数据不会上传到 Codecov,也不会与完整测试套件的覆盖率比较。
任务仅使用 PR 的只读权限,不使用密钥、不持久化检出凭据,也不恢复或保存构建缓存。
依赖定义发生变更时会报告无法比较,因为依赖固定版本不同时,两次构建无法安全地共用一份预先准备的依赖源码。
如需比较已收集的数据,将 base.info、head.info 和 JSON 元数据文件
base.json、head.json 放入报告目录。每份元数据须包含 sha 和 profile,
其中 profile 必须与 scripts/coverage/compare_simd_coverage.py 中的 PROFILE 常量完全一致。然后运行:
python3 scripts/coverage/compare_simd_coverage.py --root . \
--base "$BASE_SHA" --head "$MERGE_SHA" --reports simd-coverage
内存泄漏与多线程
test_memleak.cpp:基于 AddressSanitizer / LeakSanitizer,对索引的构造/销毁路径进行验证。test_index/test_index_concurrent.cpp:对声明了相应 feature flag 的在维护索引, 验证共享的并发添加与搜索行为。
Python 测试
tests/python/ 包含 pyvsag 的 pytest 用例。构建好 pyvsag 后:
make pyvsag PY_VERSION=3.10
cd tests/python && pytest -q
参考
- 功能测试源代码目录:
tests/ - 脚本入口:
Makefile中的test、cov、asan目标