提问者:小点点

如何编写Rust单元测试以确保发生恐慌?


我有一个Rust函数,panic在某些情况下,我希望编写一个测试用例来验证该函数是否恐慌。除了assert!assert_eq!宏之外,我找不到任何东西。有什么机制可以测试这个吗?

我可以生成一个新任务并检查该任务是否恐慌。这有意义吗?

返回结果

我希望将对Addtrait的支持添加到我正在实现的Matrix类型。此类添加的理想语法如下所示:

let m = m1 + m2 + m3;

其中m1m2m3都是矩阵。因此,add的结果类型应该是Matrix。像下面这样的东西太神秘了:

let m = ((m1 + m2).unwrap() + m3).unwrap()

同时,add()函数需要验证被添加的两个矩阵具有相同的维度。因此,如果维度不匹配,add()需要panic。可用的选项是panic!()


共3个答案

匿名用户

你可以在Rust书的测试部分找到答案。更具体地说,你想要#[should_panic]属性:

#[test]
#[should_panic]
fn test_invalid_matrices_multiplication() {
    let m1 = Matrix::new(3, 4);  // assume these are dimensions
    let m2 = Matrix::new(5, 6);
    m1 * m2
}

匿名用户

正如Francis Gagné在他的回答中提到的,我还发现#[should_panic]属性对于更复杂的测试来说不够细粒度-例如,如果我的测试设置由于某种原因失败(即我编写了一个糟糕的测试),我确实希望恐慌被认为是失败!

从Rust 1.9.0开始,std::panic::catch_unwind()可用。它允许您将预期恐慌的代码放入闭包中,只有该代码发出的恐慌才被视为预期的(即通过测试)。

#[test]
fn test_something() {
    ... //<-- Any panics here will cause test failure (good)
    let result = std::panic::catch_unwind(|| <expected_to_panic_operation_here>);
    assert!(result.is_err());  //probe further for specific error type here, if desired
}

请注意,它无法捕获非展开恐慌(例如std::进程::abort())。

匿名用户

如果您想断言只有测试函数的特定部分失败,请使用std::panic::catch_unwind()并检查它是否返回Err,例如使用is_err()。在复杂的测试函数中,这有助于确保测试不会因为早期失败而错误地通过。

Rust标准库本身的几个测试使用了这种技术。