[英]How to move tests into a separate file for binaries in Rust's Cargo?
我使用 Cargo 创建了一个新的二进制文件:
cargo new my_binary --bin
my_binary/src/main.rs
中的一个function可以用来测试:
fn function_from_main() {
println!("Test OK");
}
#[test]
fn my_test() {
function_from_main();
}
并且cargo test -- --nocapture
按预期运行测试。
将此测试移至单独文件的最直接方法是什么(将function_from_main
保留在my_binary/src/main.rs
中)?
我试图这样做但不确定如何从单独的文件中调用function_from_main
my_test
。
Rust 编程语言有一章专门介绍测试,你应该阅读它以获得基本的理解。
将单元测试(允许访问代码内部的test
)放入每个特定文件的test
模块中是很常见的:
fn function_from_main() {
println!("Test OK");
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn my_test() {
function_from_main();
}
}
模块可以移动到新文件,尽管这对于单元测试模块来说并不常见:
主文件
fn function_from_main() {
println!("Test OK");
}
#[cfg(test)]
mod test;
测试.rs
use super::*;
#[test]
fn my_test() {
function_from_main();
}
有关文件和模块如何相互映射的详细信息,请参阅将模块分成不同的文件。
单独文件中的测试更常见的情况是集成测试。 书中还有一个专门介绍板条箱外测试的部分。 这些类型的测试非常适合作为代码的使用者来执行代码。
文档的该部分包括介绍性示例和描述性文本:
我们在项目目录的顶层创建一个测试目录,在src旁边。 Cargo 知道在这个目录中寻找集成测试文件。 然后我们可以在这个目录中创建任意数量的测试文件,Cargo 会将每个文件编译为一个单独的 crate。
让我们创建一个集成测试。 将示例11-12 中的代码仍在src/lib.rs文件中,创建一个测试目录,创建一个名为tests/integration_test.rs的新文件,然后输入示例11-13 中的代码:
文件名:tests/integration_test.rs
use adder; #[test] fn it_adds_two() { assert_eq!(4, adder::add_two(2)); }
示例 11-13:加法器箱中函数的集成测试
我们在代码顶部添加了
use adder
,我们在单元测试中不需要它。 原因是 tests 目录中的每个测试都是一个单独的 crate,所以我们需要将我们的库放入每个 test crate 的范围内。
请注意,该函数被称为adder::add_two
。 关于 Rust 模块系统的更多细节可以在包、板条箱和模块章节中找到。
由于这些测试像用户一样运行您的 crate,如果您想测试一个binary ,您应该执行 binary 。 像assert_cmd这样的crate可以帮助减少这种类型的测试的痛苦。
在其他情况下,您应该将大二进制文件分解为一个大库和一个小二进制文件。 然后,您可以为库的公共 API 编写集成测试。
另见:
如果你有一个模块foo.rs并且想要将你的单元测试放在一个名为foo_test.rs的文件中,你会发现这并不总是 Rust 寻找子模块的地方。
可以使用#[path]
属性指定模块对应的文件位置:
#[cfg(test)]
#[path = "./foo_test.rs"]
mod foo_test;
你说得对; function_from_main
在main.rs
之外是不可访问的。
您需要创建一个src/lib.rs
并src/lib.rs
移动要测试的函数。 然后你就可以使用extern crate my_binary;
来自您的测试模块,并使您的函数出现在my_binary
命名空间下。
我确实相信您应该遵循阅读 Rust 书中测试章节的建议,但是,这仍然不能完全回答您的问题,如何分离测试文件和源文件。
假设您有一个lib.rs
源文件并想要一个test_lib.rs
文件。 为此,您只需要:
在你的lib.rs
:
mod test_lib;
// rest of source
然后在你的test_lib.rs
中:
#[cfg(test)]
use super::*;
#[test]
fn test1() {
// test logic
}
// more tests
然后,你和cargo test
应该都很开心。
修饰*@mmai 的回答:
#[rustfmt::skip]
#[cfg(test)]
#[path = "./foo_test.rs"]
mod foo_test;
cargo fmt
似乎对新测试文件的路径不满意。 如果有人有更好的解决方案,我会很高兴听到它,因为我希望cargo fmt
也能格式化我的测试文件!
*抱歉:我添加这个只是作为对现有答案的评论,但我没有足够的声誉。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.