如何在Cargo中查找测试资源?

55

我正在进行一个涉及文件交互的项目,希望使用文本文件来测试我的工作。但是测试不是从 tests/ 目录运行的,因此在运行 cargo run 时无法可靠地找到它们。

Cargo 是否总是从根目录运行测试(看起来是这种情况,但我没有找到任何证明)?

2个回答

88

环境变量CARGO_MANIFEST_DIR可以为您提供一个稳定的基准点来引用其他文件。这里,我们假设在箱顶有一个resources/test目录:

use std::path::PathBuf;

fn main() {
    let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    d.push("resources/test");

    println!("{}", d.display());
}

另请参阅:


这个变量可以被覆盖吗?(例如在 .env 文件中)似乎不行。 - Anatoly Bugakov
1
@AnatolyBugakov 我不明白你为什么要这样做,但是我不认为它可以被覆盖。当编译构建脚本时,Cargo会设置环境变量。如果您设置了自己的环境变量,则可以优先使用它,否则可以回退到由Cargo提供的变量。 - Shepmaster
感谢您的回复@Shepmaster。我很好奇的原因是,我正在使用工作区,并且我希望从不同的库中访问相同的测试数据。但这可能不是一个好习惯。 - Anatoly Bugakov
更好的路径连接方式是 let d: PathBuf = [env!("CARGO_MANIFEST_DIR"), "resources", "test"].iter().collect(); - Raniz

4

在@Shepmaster提供的答案基础上,假设您打算读取文件进行测试:

macro_rules! test_case {($fname:expr) => (
  concat!(env!("CARGO_MANIFEST_DIR"), "/resources/test/", $fname) // assumes Linux ('/')!
)}

这个只是在你的单元测试中简单使用:

test_case!("json_data/example.json")

更或者说是在编译时实现了相同的目标(有助于捕获缺失的文件),并且非常简洁。如果有人知道如何使这个编译时和平台无关,请随时编辑。

请参阅rust-lang问题#2841中的完整讨论


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