在 Rust 中编写全面的单元测试

4
假设我有一个名为add的Rust函数,它将两个数字相加。我想编写全面的单元测试来确保它始终正常工作。
据我所知,有两种方法可以编写这些测试:
  1. 在一个测试函数中多次使用assert_eq!
  2. 创建许多不同的函数,每个函数用于一组特定的输入/输出
这两种方法都不太理想(见下文)。在Rust中,是否有另一种更好的编写单元测试的方式?

使用多个断言

#[test]
fn test() {
  assert_eq!(add(1, 2), 3);
  assert_eq!(add(2, 4), 5);
  assert_eq!(add(2, 3), 5);
}

一切正常时,这个方法非常有效。但是如果一个断言失败了,你就不知道哪一个失败了。比如在上面的测试中,你只会得到"left: 6, right: 5"这样的提示。是哪一个断言引起了这个错误呢?虽然add 很简单,容易找出问题,但对于非常规的情况,你就没有头绪了。

使用多个函数

#[test]
fn add_1_and_2() {
  assert_eq!(add(1, 2), 3);
}

#[test]
fn add_2_and_4() {
  assert_eq!(add(2, 4), 6);
}

这解决了使用多个断言的所有问题。然而,测试变得非常冗长,每个测试都需要创建一个唯一的函数名称。想象一下一个有4-5个不同参数的函数,并且您正在测试所有组合。那将是很多难以命名的函数!但至少你会知道哪个断言失败了。

JavaScript等价物

理想情况下,我正在寻找与使用Jest的此JavaScript测试具有相同功能的解决方案。

const tests = [[1, 2, 3], [2, 4, 6]];

it.each(tests)("adding %s and %s gives %s", ([a, b, result]) => {
    expect(add(a, b)).toBe(result);
})

如果其中一项测试失败,Jest会准确地告诉您哪个测试失败了。而且实际的测试代码非常简洁易懂。

也许值得一看:https://crates.io/categories/development-tools::testing - Cryptjar
1个回答

7

部分原因是风格问题和个人偏好。第一种方法在执行许多类似操作时非常常见,因此我认为这是通常情况。

然而,这并不意味着您不能告诉哪个测试失败了。我获得的输出如下:

thread 'tests::test' panicked at 'assertion failed: `(left == right)`
  left: `6`,
 right: `5`', src/main.rs:15:9

这告诉我第15行的断言失败了。如果你正在调用一些进行测试并调用 assert_eq! 的函数,并且你需要知道哪个调用导致它失败,可以使用 RUST_BACKTRACE=1 查看回溯并找到相应的行号。

你还可以编写一个描述(带有附加格式化参数,就像 format! 一样):

#[test]
fn test() {
    assert_eq!(add(1, 2), 3, "add 1 and 2");
    assert_eq!(add(2, 4), 5, "add 2 and 4");
    assert_eq!(add(2, 3), 5, "add 2 and 3");
}

然后你会在输出中看到失败的测试名称(现在注意到它说“add 2 and 4”):

thread 'tests::test' panicked at 'assertion failed: `(left == right)`
  left: `6`,
 right: `5`: add 2 and 4', src/main.rs:15:9

如果您更喜欢基于表格的方法,也有相应的方法可供选择:

#[test]
fn test() {
    let conditions = &[(1, 2, 3), (2, 4, 5), (2, 3, 5)];

    for (a1, a2, sum) in conditions {
        assert_eq!(add(*a1, *a2), *sum, "add {} and {}", a1, a2);
    }
}

或者,如果您的测试参数很长且不易于打印:

#[test]
fn test() {
    let conditions = &[
        (1, 2, 3, "test case 1"),
        (2, 4, 5, "test case 2"),
        (2, 3, 5, "test case for bug #12345"),
    ];

    for (a1, a2, sum, desc) in conditions {
        assert_eq!(add(*a1, *a2), *sum, "{}", desc);
    }
}

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