将自定义命令行参数传递给 Rust 测试

Passing custom command-line arguments to a Rust test

我有一个 Rust 测试,它使用 doctest 委托给 C++ 测试套件,并想将命令行参数传递给它。我的第一次尝试是

// in mod ffi
pub fn run_tests(cli_args: &mut [String]) -> bool;

#[test]
fn run_cpp_test_suite() {
    let mut cli_args: Vec<String> = env::args().collect();
    if !ffi::run_tests(
        cli_args.as_mut_slice(),
    ) {
        panic!("C++ test suite reported errors");
    }
}

因为cargo test help显示

USAGE:
    cargo.exe test [OPTIONS] [TESTNAME] [-- <args>...]

我预计

cargo test -- --test-case="X"

run_cpp_test_suite访问并传递--test-case="X"参数。但事实并非如此;我得到 error: Unrecognized option: 'test-case'cargo test -- --help 表明它有一组固定的选项

Usage: --help [OPTIONS] [FILTER]

Options:
        --include-ignored 
                        Run ignored and not ignored tests
        --ignored       Run only ignored tests
...

我的另一个想法是在环境变量中传递参数,即

DOCTEST_ARGS="--test-case='X'" cargo test

但是我需要以某种方式将该字符串拆分为 Rust 或 C++ 中的参数(至少正确处理空格和引号)。

涉及两个个Rust工具链when you run cargo test

cargo test 本身会在您的包或工作区中查找所有可测试的目标,使用 cfg(test) 构建它们,然后 运行 那些二进制文件。 cargo test 处理 -- 左边的参数,右边的参数传递给二进制文件。

然后,

Tests are built with the --test option to rustc which creates an executable with a main function that automatically runs all functions annotated with the #[test] attribute in multiple threads. #[bench] annotated functions will also be run with one iteration to verify that they are functional.

The libtest harness may be disabled by setting harness = false in the target manifest settings, in which case your code will need to provide its own main function to handle running tests.

“libtest harness”拒绝了您的额外论点。在您的情况下,由于您打算 运行 整个其他测试套件,我认为禁用线束是合适的。

  1. 将您的委托代码移动到它自己的文件中,通常位于包目录中的 tests/

    Cargo.toml
    src/
        lib.rs
        ...
    tests/
        cpp_test.rs
    
  2. 在你的Cargo.toml中为它写一个明确的target section,禁用线束:

    [[test]]
    name = "cpp_test"
    # path = "tests/cpp_test.rs"   # This is automatic; you can use a different path if you really want to.
    harness = false
    
  3. cpp_test.rs 中,不是编写带有 #[test] 属性的函数,而是编写一个普通的 main 函数,该函数读取 env::args() 并调用C++ 测试。

[免责声明:我熟悉这些机制,因为我使用了 Criterion 基准测试(同样需要禁用默认工具),但我实际上并没有按照您正在寻找的方式编写带有自定义参数的测试.所以,有些细节可能是错误的。如果有任何需要更正的地方,请告诉我。]

除了 , if you don't want to write your own test harness, you can use the shell-words crate 按照 shell 规则将环境变量拆分为单独的参数外:

let args = var ("DOCTEST_ARGS").unwrap_or_else (|_| String::new());
let args = shell_words::split (&args).expect ("failed to parse DOCTEST_ARGS");

Command::new ("cpptest")
    .args (args)
    .spawn()
    .expect ("failed to start subprocess")
    .wait()
    .expect ("failed to wait for subprocess");