有没有一种惯用的方式可以为集成测试和基准测试共享实用函数?

34

我有一个Rust项目,其中包含集成测试(在/tests目录中)和基准测试(在/benches目录中)。我需要在测试和基准中使用一些实用函数,但它们与我的创建本身无关,因此我不能将它们放入/utils目录中。

如何处理这种情况的惯用方式是什么?


如果您要重复使用它们,也许可以使用 extern crate? - Boiethios
这不是通用函数,而只是与此项目相关的辅助函数。因此,我认为这不是一个好的解决方案。 - Constantine
3个回答

44

创建共享的crate(首选)

如评论所述,创建一个新的crate。你不必将crate发布到crates.io。只需将其作为本地未发布的crate 保留在项目内,并将其标记为仅用于开发的依赖项

这最好与Cargo解析器的版本2一起使用。为了获得更好的性能,考虑使用Cargo工作区

.
├── Cargo.toml
├── src
│   └── lib.rs
├── tests
│   └── integration.rs
└── utilities
    ├── Cargo.toml
    └── src
        └── lib.rs

Cargo.toml

# ...

[dev-dependencies]
utilities = { path = "utilities" }

utilities/src/lib.rs

pub fn shared_code() {
    println!("I am shared code");
}

tests/integration.rs

extern crate utilities;

#[test]
fn a_test() {
    utilities::shared_code();
}

一个仅用于测试的模块

你可以将一个模块放在你的 crate 中,只有当特定功能被传递时才会被编译。这与单元测试使用的概念相同。它的优点是可以访问库代码的内部。缺点是每次运行代码都需要传递标志。

这最好与 Cargo 解析器的第 2 版 一起使用。

Cargo.toml

# ...

[features]
test-utilities = []

src/lib.rs

#[cfg(feature = "test-utilities")]
pub mod test_utilities {
    pub fn shared_code() {
        println!("I'm inside the library")
    }
}

tests/integration.rs

extern crate the_library;

#[test]
fn a_test() {
    the_library::test_utilities::shared_code();
}

执行

cargo test --features=test-utilities

这段内容涉及编程,建议使用Cargo解析器版本2

使用任意文件路径中的模块

这种方法让我感到不舒服,而且与常规方式相去甚远。

utilities.rs

pub fn shared_code() {
    println!("This is just sitting out there");
}

tests/integration.rs

#[path = "../utilities.rs"]
mod utilities;

#[test]
fn a_test() {
    utilities::shared_code();
}

另请参阅:


@jean553 是的,只有库包才能被其他包重用。 - Shepmaster
@Greg0ry 你提供它已经有4年了 - 你和我使用不同的日历。这个答案是在2017-06-14创建的(将鼠标悬停在“回答”旁边的日期上以获取ISO格式日期),大约一年多前。但是,我不这么认为。 - Shepmaster
啊,我真傻...不管怎样,再次感谢,最终我选择了仅测试模块。 - Greg0ry
4
这条评论 认为“共享 crate”方法会防止你发布主 crate (除非你也发布 utilities crate)。如果这是正确的,我认为答案应该提到这一点。 - Nickolay
@JonathanTran 工作区在这里并不会实质性地改变任何计算。工作区只会减少您编译给定共享 crate 的次数。 - Shepmaster
显示剩余6条评论

7
您可以将这些实用函数添加到主箱内的“pub”模块中,并使用“#[doc(hidden)]”或“#![doc(hidden)]”属性隐藏它们,以免被文档生成器记录。额外的注释将指导读者为什么需要这样做。

2
对于应该发布的板条箱,这是更好的解决方案:crates.io将拒绝路径依赖项,因此您必须发布您的util crate,或将它们放入未记录的模块中。我认为后者更可取。 - antifuchs

4

虽然这对基准测试没有帮助,但我来到这里是为了寻找一种可以在多个集成测试中实现此功能的方法,并且后来发现你可以按照以下集成测试进行:

具有共同代码的模块遵循普通模块规则,因此可以将常见模块创建为 tests/common/mod.rs。

来源:https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接