...

Rust数据驱动-参数化测试

需求

假如有以下测试用例,同样的逻辑,我们需要测试多组数据

mod tests {
    #[test]
    fn test_add() {
        let a = 1;
        let b = 2;
        assert_eq!(a + b, 3);
    }
}

一般情况下我们不在用例中使用for循环(即subtests子测试模式)来验证多组数据。

mod tests {
    #[test]
    fn test_add() {
        for a in [1, 2, 3] {
            assert_eq!(a + a, 2 * a);
        }
    }
}

因为这样只是一个用例,而不是一组数据一个用例,同时前面的数据出错也会导致后面的数据测试不到。

使用三方包-实现数据驱动测试

Rust中想要进行参数化测试,可以使用三方包,或者自己编写宏,常用的数据驱动三方包如下:

  • test-case: 支持通过标记进行参数化
  • rtest:支持参数化标记和自定义fixture依赖
  • test-generator: 支持基于文件的数据驱动
  • datatesgt: 支持基于稳定的数据驱动和通过yaml生成多个结构体数据

以test-case为例

mod tests {
    use test_case::test_case;
    #[test_case(1, 1, 2; "1+1应等于2")]
    #[test_case(2, 3, 5; "2+3应等于5")]
    #[test_case(0, 0, 0; "0+0应等于0")]
    fn test_add(a: i32, b: i32, excepted: i32) {
        assert_eq!(a + b, excepted);
    }
}

测试结果如图:
image

也可以在项目中使用cargo test执行所有测试,结果如下:

running 3 tests
test add_test::tests::test_add::_0_0应等于0 ... ok
test add_test::tests::test_add::_1_1应等于2 ... ok
test add_test::tests::test_add::_2_3应等于5 ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

自定义宏-实现数据驱动测试

当然,也可以自己编写宏实现,例如:

macro_rules! make_testcase {
    ($test_func_name:ident, $a:expr, $b:expr, $excepted:expr) => {
        #[test]
        fn $test_func_name() {
            assert_eq!($a + $b, $excepted);
        }
    }
}

mod tests {
    make_testcase!(test_add_0, 1, 2, 3);
    make_testcase!(test_add_1, 2, 3, 5);
    make_testcase!(test_add_2, 0, 0, 0);
}

多轮随机数据测试

上面的数据驱动都是基于明确已有的多组数据进行测试的,如果想要使用多轮随机数据进行测试,可通过 test-case + seq + 自定义宏来实现,例如:

macro_rules! make_testcases {
    ($count:expr) => {
        mod tests {
            use rand::Rng;
            use seq_macro::seq;
            use test_case::test_case;

            seq!(N in 0..$count {
                #(#[test_case(N)])*
                fn test_add(index: usize) {
                    let mut rng = rand::thread_rng();
                    let a =  rng.gen_range(0..10);
                    assert_eq!(a + a, 2 * a)
                }
            });
        }
    };
}

mod tests {
    make_testcases!(3);
}

依赖Cargo.toml

[dependencies]
test-case = "*"
seq-macro  = "*"
rand = "*"

执行效果如下:

image

参考:

posted @ 2024-05-14 15:22  韩志超  阅读(12)  评论(0编辑  收藏  举报