【问题标题】:Writing comprehensive unit tests in rust在 rust 中编写全面的单元测试
【发布时间】:2021-07-01 21:55:37
【问题描述】:

假设我有一个名为 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 会准确告诉您是哪一项。而且实际的测试代码非常简洁易读。

【问题讨论】:

标签: unit-testing testing rust


【解决方案1】:

部分原因是风格问题和个人喜好。第一种方法在执行许多类似操作时非常常见,所以我会说它很常见。

但是,这并不意味着您无法判断哪个测试失败了。我得到这样的输出:

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");
}

然后您会在输出中看到失败的测试名称(注意它现在显示“添加 2 和 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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2012-02-03
    • 2010-10-05
    相关资源
    最近更新 更多