如何在Rust中使用assert_eq!来显示多行字符串

huangapple go评论91阅读模式
英文:

How can I make assert_eq! in Rust show multiline strings

问题

以下是要翻译的内容:

我有以下的Rust单元测试:

  1. #[test]
  2. fn test_multiline_strings_are_equal() {
  3. let expected = "\
  4. one
  5. two
  6. three
  7. four
  8. ";
  9. let actual = "\
  10. one
  11. two
  12. four
  13. ";
  14. assert_eq!(actual, expected);
  15. }

当它失败时,会输出以下内容:

  1. ---- printer::tests::test_multiline_strings_are_equal stdout ----
  2. thread 'printer::tests::test_multiline_strings_are_equal' panicked at 'assertion failed: `(left == right)`
  3. left: "one\ntwo\nfour\n",
  4. right: "one\ntwo\nthree\nfour\n"', src\printer.rs:600:9

有人可以告诉我如何使它显示"one"、"two"、"three"和"four"在不同的行上,以便更容易进行比较吗?

英文:

I have the following Rust unit test:

  1. #[test]
  2. fn test_multiline_strings_are_equal() {
  3. let expected = "\
  4. one
  5. two
  6. three
  7. four
  8. ";
  9. let actual = "\
  10. one
  11. two
  12. four
  13. ";
  14. assert_eq!(actual, expected);
  15. }

When it fails, it outputs the following:

  1. ---- printer::tests::test_multiline_strings_are_equal stdout ----
  2. thread 'printer::tests::test_multiline_strings_are_equal' panicked at 'assertion failed: `(left == right)`
  3. left: `"one\ntwo\nfour\n"`,
  4. right: `"one\ntwo\nthree\nfour\n"`', src\printer.rs:600:9

Can anyone tell me how to make it show "one", "two", "three" and "four" on separate lines, for easier comparison?

答案1

得分: 7

The pretty_assertions库可以实现这一功能。只需添加以下代码:

  1. use pretty_assertions::assert_eq;

其替代的 assert_eq! 宏将产生逐行差异;在你的示例中:

  1. Diff < left / right > :
  2. one
  3. two
  4. >three
  5. four

它还适用于非字符串值的 Debug 输出:

  1. use pretty_assertions::assert_eq;
  2. #[test]
  3. fn test_struct() {
  4. #[derive(Debug, PartialEq)]
  5. struct Foo {
  6. x: &'static str,
  7. y: &'static str,
  8. }
  9. assert_eq!(
  10. Foo { x: "x", y: "y" },
  11. Foo {
  12. x: "x",
  13. y: "surprise!",
  14. }
  15. );
  16. }
  1. Diff < left / right > :
  2. Foo {
  3. x: "x",
  4. < y: "y",
  5. > y: "surprise!",
  6. }
英文:

The pretty_assertions library does this. Just add

  1. use pretty_assertions::assert_eq;

and its replacement assert_eq! macro will produce a line-by-line diff; in your example:

  1. Diff < left / right > :
  2. one
  3. two
  4. >three
  5. four

It also works with the Debug output of non-string values:

  1. use pretty_assertions::assert_eq;
  2. #[test]
  3. fn test_struct() {
  4. #[derive(Debug, PartialEq)]
  5. struct Foo {
  6. x: &'static str,
  7. y: &'static str,
  8. }
  9. assert_eq!(
  10. Foo { x: "x", y: "y" },
  11. Foo {
  12. x: "x",
  13. y: "surprise!",
  14. }
  15. );
  16. }
  1. Diff < left / right > :
  2. Foo {
  3. x: "x",
  4. < y: "y",
  5. > y: "surprise!",
  6. }

答案2

得分: 3

The assert_eq! 宏将在数值不相等时 "打印表达式的调试表示形式及其值"。这使用了 Debug 格式说明符,对于字符串,它会转义换行符和其他控制字符。因此,你不能在不使用某种使 Debug 实现使用 Display 实现的类型包装字符串的情况下覆盖它。

然而,一个替代方法是该宏允许你使用普通格式化语法提供自己的消息。因此,你可以提供非调试输出:

  1. assert_eq!(actual, expected, "\n扩展左侧: {actual}\n扩展右侧: {expected}\n");
  1. 线程 'test_multiline_strings_are_equal' 'assertion failed: `(left == right)`
  2. left: `"one\ntwo\nfour\n"`,
  3. right: `"one\ntwo\nthree\nfour\n"`:
  4. 扩展左侧: one
  5. two
  6. four
  7. 扩展右侧: one
  8. two
  9. three
  10. four
  11. ', src/lib.rs:14:5

这看起来有点奇怪,因为我不认为该宏真的期望自定义消息具有换行符(参见末尾的 src/lib.rs:14:5),但希望它能够工作得足够好。

如果这不够好,自己制作一个宏也不会太难。

英文:

The assert_eq! macro will "print the values of the expressions with their debug representations" if the values are not equal. This uses the Debug format specifier, which for strings will escape newlines and other control characters. So you can't override that without wrapping the strings in some type that makes the Debug implementation use the Display implementation.

An alternative though is the macro allows you to provide your own message using the normal formatting syntax. So you could provide the non-debug output as well:

  1. assert_eq!(actual, expected, "\n expanded left: {actual}\nexpanded right: {expected}\n");
  1. thread 'test_multiline_strings_are_equal' panicked at 'assertion failed: `(left == right)`
  2. left: `"one\ntwo\nfour\n"`,
  3. right: `"one\ntwo\nthree\nfour\n"`:
  4. expanded left: one
  5. two
  6. four
  7. expanded right: one
  8. two
  9. three
  10. four
  11. ', src/lib.rs:14:5

It looks a bit weird since I don't think the macro was really expecting the custom message to have newlines (see the trailing ', src/lib.rs:14:5) but it hopefully it works well enough.

If that's not good enough, it wouldn't be too hard to make your own macro.

huangapple
  • 本文由 发表于 2023年5月13日 23:05:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76243409.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定