Rust 宏生成多个单独的测试

Kad*_*BOT 5 testing macros rust

是否可以有一个生成独立测试的宏?我有两个文本文件,一个带有输入,另一个带有输出。文本文件中的每一新行都代表一个新测试。目前,这就是我运行测试的方式:

    #[test]
    fn it_works() {
        let input = read_file("input.txt").expect("failed to read input");
        let input = input.split("\n").collect::<Vec<_>>();

        let output = read_file("output.txt").expect("failed to read output");
        let output = output.split("\n").collect::<Vec<_>>();

        input.iter().zip(output).for_each(|(a, b)| {
            println!("a: {}, b: {}", a, b);
            assert_eq!(b, get_result(a));
        })

Run Code Online (Sandbox Code Playgroud)

但是,正如您所看到的,如果一个测试失败,那么所有测试都会失败,因为单个测试中存在循环。我需要每次迭代都是一个单独且孤立的测试,而不必重复自己。

所以我想知道是否可以通过使用宏来实现这一点?

理想情况下,宏会输出如下内容:

    #[test]
    fn it_works_1() {
        let input = read_file("input.txt").expect("failed to read input");
        let input = input.split("\n").collect::<Vec<_>>();

        let output = read_file("output.txt").expect("failed to read output");
        let output = output.split("\n").collect::<Vec<_>>();

        assert_eq!(output[0], get_result(input[0])); // first test
    }

    #[test]
    fn it_works_2() {
        let input = read_file("input.txt").expect("failed to read input");
        let input = input.split("\n").collect::<Vec<_>>();

        let output = read_file("output.txt").expect("failed to read output");
        let output = output.split("\n").collect::<Vec<_>>();

        assert_eq!(output[1], get_result(input[1])); // second test
    }

    // ... the N remaining tests: it_works_n() 
Run Code Online (Sandbox Code Playgroud)

Pet*_*all 3

您不能使用声明性宏来执行此操作,因为声明性宏无法生成标识符来命名测试函数。但是,您可以使用诸如 之类的包test-case,它可以使用不同的输入运行相同的测试:

use test_case::test_case;

#[test_case(0)]
#[test_case(1)]
#[test_case(2)]
#[test]
fn it_works(index: usize) {
    let input = read_file("input.txt").expect("failed to read input");
    let input = input.split("\n").collect::<Vec<_>>();

    let output = read_file("output.txt").expect("failed to read output");
    let output = output.split("\n").collect::<Vec<_>>();

    assert_eq!(output[index], get_result(input[index])); // first test
}
Run Code Online (Sandbox Code Playgroud)

如果您有很多不同的输入要测试,您可以使用声明性宏来生成上面的代码,这将添加所有注释#[test_case]