测试
测试
测试对于确保 DataFusion 正常运行、避免在重构过程中被意外破坏至关重要。所有新功能都应具备测试覆盖,完整的测试套件会作为 CI 的一部分运行。
测试快速上手
在开发某个功能或修复某个缺陷时,最佳实践是先运行最小的、足以让你对自己的改动有信心的测试集合,然后再按需扩大范围。
首先,运行你所修改的 crate 中的测试。例如,如果你修改了 datafusion-optimizer/src 中的文件,就运行对应 crate 的测试:
cargo test -p datafusion-optimizer然后,运行 sqllogictest 测试套件,它在开发过程中提供了良好的速度与覆盖率的平衡:运行速度快,同时能对 DataFusion 中的大部分 SQL 行为提供广泛的回归覆盖。
cargo test --profile=ci --test sqllogictests最后,在提交 PR 之前,请运行 datafusion 和 datafusion-cli 核心 crate 的测试:
cargo test -p datafusion
cargo test -p datafusion-cli某些集成测试需要可选的外部服务(例如由 Docker 支撑的容器),在服务不可用时可能会跳过执行。
测试概览
DataFusion 的测试金字塔包含多个层级的测试,并尽量遵循《Rust 程序设计语言》中描述的 Rust 标准测试组织方式。
使用 cargo 运行测试:
cargo test你也可以使用其他运行器,例如 cargo-nextest。
cargo nextest run单元测试
针对单个模块中代码的测试,按照 Rust 的惯例,定义在同一源文件的 test 模块中。
例如,要运行 datafusion crate 中的测试:
cargo test -p datafusiontest_util 模块提供了一些有用的宏,用于高效地编写单元测试,例如针对 RecordBatches 的 assert_batches_sorted_eq 和 assert_batches_eq,以及在整个代码库中被广泛使用的 assert_contains / assert_not_contains。
sqllogictests 测试
DataFusion 的 SQL 实现是使用 sqllogictest 进行测试的。你可以使用如下命令运行这些测试:
# Run all tests
cargo test --profile=ci --test sqllogictests
# Run a specific test file
cargo test --profile=ci --test sqllogictests -- aggregate.slt
# Run a specific test file and update expected outputs
cargo test --profile=ci --test sqllogictests -- aggregate.slt --complete
# Run and update expected outputs for all test files
cargo test --profile=ci --test sqllogictests -- --completesqllogictests 对于习惯编写 .rs 测试的新贡献者来说可能没那么方便,因为需要学习另一个工具。然而,基于 sqllogictest 的测试在开发和维护上要容易得多,因为它们 1) 不需要缓慢的重新编译/链接循环,2) 可以自动更新。
与 DuckDB 等类似系统一样,DataFusion 选择用稍高的参与门槛来换取长期的可维护性。
DataFusion 在合并队列中运行 SQLite 的测试套件,然后才会将 PR 合并到 main 分支。有关本地运行的说明,请参阅运行测试:sqlite。
快照测试(cargo insta)
Insta 被用于快照测试。每次运行测试时都会生成快照并进行比较。如果输出发生变化,测试将会失败。
要查看这些变更,可以使用 Insta 命令行工具:
cargo install cargo-insta
cargo insta review扩展测试
DataFusion 拥有扩展测试(定义于 extended.yml),其运行耗时远超标准测试套件。这些测试提供额外的正确性覆盖,并且必须在合并队列中通过,PR 才能合入 main 分支。
为了节省 CI 资源,这些测试不会在普通的 PR 更新时运行。它们也会在推送至发布分支(branch-*)时运行。你也可以手动运行它们。
有关本地 SQLite 的测试说明,请参阅文档中的说明。
Rust 集成测试
在 tests 目录中,有若干针对 DataFusion 库的公共接口测试。
你可以像使用普通命令那样,通过 cargo 单独运行这些测试,例如:
cargo test -p datafusion --test parquet_integrationSQL “模糊”测试
DataFusion 使用 SQLancer 进行"模糊"测试:它生成随机 SQL 查询并在 DataFusion 上执行,以发现缺陷。
相关代码位于 datafusion-sqllancer 仓库,欢迎进一步贡献。感谢 @2010YOUY01 的最初实现。
文档示例
我们使用 Rust 的 doctest 来验证文档中的示例正确且不过时。这些测试会作为 CI 的一部分运行,你也可以在本地使用以下命令运行它们:
cargo test --docAPI 文档示例
与其他 Rust 项目一样,.rs 文件中文档注释里的示例会被自动检查,以确保它们能够正常运行,并随代码一起演进。
用户指南文档
用户指南中的 Rust 示例代码(任何标记为 ```rust 的内容)也会通过 doc_comment crate 以相同的方式进行测试。更多详情请参阅 core/src/lib.rs 的末尾。
文档链接检查
./dev/rust_lint.sh 会运行内部 Markdown 链接检查。如果缺少 lychee,该脚本会安装 ci/scripts/utils/tool_versions.sh 中固定(pin)的版本。如果已经安装过,脚本会直接使用现有安装,即使其版本与固定版本不同。
单独运行该检查:
source ci/scripts/utils/tool_versions.sh
cargo install lychee --locked --version "${LYCHEE_VERSION}"
bash ci/scripts/markdown_link_check.sh注意事项:
- 该脚本使用
bash运行,并兼容 macOS 上的默认 Bash(不依赖mapfile)。 - CI 配置目前只检查内部 Markdown 链接。外部
http(s)和mailto链接会被排除,以避免不稳定的失败。 - 该检查只报告失效的链接。
./dev/rust_lint.sh --write不会修改它们。
当链接失效时,lychee 会打印出出错的文件以及 URL/路径。例如:
[docs/source/user-guide/cli/overview.md]:
[ERROR] file:///.../docs/source/user-guide/cli/missing-page.md | Cannot find file: File not found. Check if file exists and path is correctRust 文档注释会在 CI 中由 rustdoc 校验,也可以在本地通过以下命令检查:
bash ci/scripts/rust_docs.shASF 状态检查验证
ci/scripts/check_asf_yaml_status_checks.py 会检查 .asf.yaml 中每个必需的状态检查是否与 .github/workflows 中的某个任务相对应,并检查 rust.yml 在推送到 main 时是否只跳过其列出的任务。./dev/rust_lint.sh 会运行该脚本,需要 python3 和 PyYAML。uv 工作区同时提供了这两者:
uv run ./dev/rust_lint.sh单独运行该检查:
uv run python3 ci/scripts/check_asf_yaml_status_checks.py安全审计
ci/scripts/security_audit.sh 会针对根目录的 Cargo.lock 运行 cargo audit,并使用 CI 所采用的漏洞例外配置。./dev/rust_lint.sh 也会运行它,并在缺失时安装 cargo-audit。若要单独运行该审计:
./ci/scripts/security_audit.sh该审计会拉取 RustSec 安全公告数据库。新增一条公告,或者 cargo-audit 版本不同,都可能在仓库没有任何改动的情况下导致结果变化。
大文件检查
ci/scripts/check_large_files.sh 会在基础引用(base ref)到目标引用(head ref)之间提交的任何文件超过 1.5 MB 时失败,这与 "Large files PR check" 工作流在拉取请求上执行的检查相同。./dev/rust_lint.sh 会针对指向 apache/datafusion 的远程上 HEAD 与 main 的合并基准运行该脚本;如果不存在这样的远程,则使用 origin。若要单独运行该检查,或针对不同的范围运行:
./ci/scripts/check_large_files.sh
./ci/scripts/check_large_files.sh --base upstream/main --head my-branch仅会检查已提交的文件。请先提交更改,再运行该脚本。
依赖检查
CI 会运行两项依赖检查,而 ./dev/rust_lint.sh 会同时运行这两项:
ci/scripts/check_circular_dependencies.sh会构建并运行dev/depcheck,若 DataFusion 各 crate 之间存在循环依赖则判定失败。ci/scripts/check_unused_dependencies.sh会在仓库根目录运行cargo machete --with-metadata。如果缺少 cargo-machete,该检查套件会安装ci/scripts/utils/tool_versions.sh中指定的版本。
若要单独运行其中任意一项检查:
./ci/scripts/check_circular_dependencies.sh
./ci/scripts/check_unused_dependencies.shExamples README 检查
datafusion-examples/README.md 是由 datafusion-examples/examples/<group>/main.rs 中的文档注释生成的。ci/scripts/check_examples_docs.sh 会重新生成该文件,如果已提交的文件与生成结果不同,脚本将失败。./dev/rust_lint.sh 会运行该脚本,并且需要 cargo 和 npx。若要单独运行此检查,或更新 README:
./ci/scripts/check_examples_docs.sh
./ci/scripts/check_examples_docs.sh --write配置与函数文档检查
configs.md、aggregate_functions.md、scalar_functions.md 和 window_functions.md 是由 dev/update_config_docs.sh 和 dev/update_function_docs.sh 生成的。要检查它们是否为最新版本,请运行 ci/scripts/check_generated_docs.sh 脚本,该脚本也是 ./dev/rust_lint.sh 执行流程的一部分。使用 --write 参数运行它可以更新这些页面。
基准测试
Criterion 基准测试
Criterion 是一个由统计数据驱动的微基准测试框架,DataFusion 用它来评估特定代码路径的性能。其中,criterion 基准测试既有助于指导优化工作,也能防止 DataFusion 出现性能回退。
Criterion 与 Cargo 内置的基准测试支持集成,可以
cargo bench --bench BENCHMARK_NAME完整基准测试列表见此处。
cargo-criterion 也可用于生成更高级的报告。
Parquet SQL 基准测试
Parquet SQL 基准测试可通过以下方式运行:
cargo bench --bench parquet_query_sql这些测试会随机生成一个 parquet 文件,然后针对该文件运行来自 parquet_query_sql.sql 的查询进行基准测试。因此,这是一种为特定查询路径和/或数据路径快速添加测试覆盖的方式。
如果设置了环境变量 PARQUET_FILE,基准测试将针对该文件运行查询,而不是使用随机生成的文件。这在需要针对同一份源数据进行多次运行(可能使用不同的代码),或者针对自定义数据集进行测试时非常有用。
基准测试会在退出时自动删除生成的 parquet 文件,但如果被中断(例如按下 CTRL+C),则不会删除。这样便于事后分析该特定文件,或将其保留下来在后续运行中配合 PARQUET_FILE 使用。
比较基线
默认情况下,Criterion.rs 会将测量结果与上一次运行(如果有)进行比较。有时,保留一组测量结果以供多次运行使用会很有帮助。例如,你可能希望在多次修改代码的同时与 master 分支进行比较。针对这种情况,Criterion.rs 支持自定义基线。
git checkout main
cargo bench --bench sql_planner -- --save-baseline main
git checkout YOUR_BRANCH
cargo bench --bench sql_planner -- --baseline main注意:在 macOS 上,运行 cargo bench 可能需要使用 sudo。
sudo cargo bench ...有关 基准线(Baselines)的更多信息
上游基准测试套件
关于如何针对 DataFusion 运行上游基准测试套件的说明和工具,可以在 benchmarks 目录中找到。
这些资源对于与其他 Arrow 实现和查询引擎进行对比评估非常有价值。
评论
登录后参与评论
KnowForge