为什么需要 `assert_eq` 和 `assert_ne`,而简单的 `assert` 就足够了呢?

11

assert!(a == b)assert_eq!(a, b) 更加简洁,并且在我的看法中更易读。

错误信息基本相同:

thread 'main' panicked at 'assertion failed: `(left == right)` (left: `1`, right: `2`)', src\main.rs:41
或者
thread 'main' panicked at 'assertion failed: 1 == 2', src\main.rs:41

实际上,这个问题不仅仅涉及到Rust;我经常在单元测试框架中看到这些不同的断言宏或函数:

  • Cpputest有CHECKCHECK_FALSECHECK_EQUAL等等;
  • Googletest有EXPECT_GTEXPECT_EQ等等;
  • JUnit有assertEqualsassertFalse等等。

通常还会针对某些特定类型(比如字符串或数组)进行断言。这是什么意思呢?

1个回答

17

线程'main'在 'assertion failed: 1 == 2' 处发生了恐慌(panic)。

你的示例太简单,无法展示使用 assert_eq! 的巨大优势。请考虑以下代码:

let s = "Hello".to_string();
assert!(&s == "Bye");

这是导致恐慌消息的结果:

'assertion failed: &s == "Bye"'    

现在让我们看看当我们使用 assert_eq! 时会发生什么:

let s = "Hello".to_string();
assert_eq!(&s, "Bye");

消息:

'assertion failed: `(left == right)` (left: `"Hello"`, right: `"Bye"`)'

这条消息提供了比以前更多的见解。其他单元测试系统通常也会这样做。


2
没错。你的测试框架应该帮助你。仅仅说“测试失败”比说“测试失败因为这些原因”要少得多。我们创建具有名称的函数的整个方面也是为了拥有可读和可理解的代码。 - Shepmaster
@Shepmaster 我不确定assert_eq本身更易读,但更详细的错误信息当然更好。 - Amomum
1
@Amomum:实际上有一个RFC来改进assert_eq,与此同时,您可能会对pretty_assertions crate感兴趣。 - Matthieu M.
2
现在的问题是:为什么要明确地写出 assert_eq(<expr>, <expr>)?难道不可能通过模式匹配 assert!(<expr> == <expr>) 并且只做正确的事情™ 吗? - Lukas Kalbertodt
@LukasKalbertodt:可以说,有了assert_eq!,我们就不需要这样的复杂性。 :P - E net4
@LukasKalbertodt的评论让我感同身受。假设有一种方法可以使用==!=生成等效的输出,那么为已经存在于语言中的语法创建新的DSL似乎是不太理想的。有时我们还需要使用>,<,>=,<=,但这些在assert_*宏DSL中似乎不存在。令人困惑。 - U007D

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