【问题标题】:How to have mocha show entire object in diff on assertion error?如何让 mocha 在断言错误的差异中显示整个对象?
【发布时间】:2017-08-25 12:48:37
【问题描述】:

我有一个使用 mocha 和 chai 的期望创建的单元测试测试用例,我在其中深入比较了一组值对象与 JSON 文件的解析内容。

我的记录对象有大约 20 个属性,目前只有价格会导致不匹配。在 diff 中,我只看到其中的五个。

 expect(records).to.deep.equal(expected);

       "data": {
  -      "price": 3578
  +      "price": 3438
         "not_important": "foo"
         "also_not_important": "bar"
       }
       "data": {
  -      "price": 1828
  +      "price": 1698
         "not_important": "foo"
         "also_not_important": "bar"
       }

这在大多数情况下是有用的默认值,但在这一个中它混淆了哪个特定数据对象破坏了断言,因为我在这里只看到冗余数据。

假设数据对象中有一个important 属性,它可以很清楚地说明什么期望破坏了测试。因此,我希望能够配置显示哪些属性或在 diff 中显示整个对象。

如何配置 mocha 的差异显示?


这是一个展示问题的人为的元句法示例:

import {expect} from "chai";

describe(("diff problem"), () => {
    it("should show case that the diff is not shown properly", () => {
        const actual = {
            a: 1,
            troiz: 0,
            bar: 0,
            baz: 2,
            poit: 3,
            narf: 4,
            fizzbuzz: 117,
            fizz: 5,
            buzz: 4,
            waldo: 115,
            mos: 85465,
            important: "THIS IS IMPORTANT",
        };

        const expected = {
            ...actual,
            a: 0,
        };

        return expect(actual).to.deep.equal(expected);
    });
});

该测试用例的输出将是:

2) SourceParser 差异问题应该在一个属性的错误上显示整个差异:

  AssertionError: expected { Object (a, troiz, ...) } to deeply equal { Object (a, troiz, ...) }
  + expected - actual

   {
  -  "a": 1
  +  "a": 0
     "bar": 0
     "baz": 2
     "buzz": 4
     "fizz": 5

不过,看看important: "THIS IS IMPORTANT" 也会很有帮助。


这里是数组情况的修改示例:

describe(("diff problem with an array"), () => {
    it("should show case that the diff is not shown properly for deep equal of arrays", () => {
        const anEntity = {
            a: 1,
            troiz: 0,
            bar: 0,
            baz: 2,
            poit: 3,
            narf: 4,
            fizzbuzz: 117,
            fizz: 5,
            buzz: 4,
            waldo: 115,
            mos: 85465,
            important: "IMPORTANT", // assume that each item has a unique important property, which is why it's helpful for it to be shown
        };

        const offendingItem = {
            ...anEntity,
            a: 0,
        };

        const actual = [
            anEntity,
            offendingItem,
            anEntity,
        ];

        const expected = [
            anEntity,
            anEntity,
            anEntity,
        ];

        return expect(actual).to.deep.equal(expected);
    });

输出将是:

  AssertionError: expected [ Array(3) ] to deeply equal [ Array(3) ]
  + expected - actual

       "troiz": 0
       "waldo": 115
     }
     {
  -    "a": 0
  +    "a": 1
       "bar": 0
       "baz": 2
       "buzz": 4
       "fizz": 5

Louis 修改 chai 的答案并不会变得更好,因为它只会先转储整个实际数组,然后显示无用的差异:

AssertionError: expected [ { a: 1,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' },
  { a: 0,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' },
  { a: 1,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' } ] to deeply equal [ { a: 1,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' },
  { a: 1,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' },
  { a: 1,
    troiz: 0,
    bar: 0,
    baz: 2,
    poit: 3,
    narf: 4,
    fizzbuzz: 117,
    fizz: 5,
    buzz: 4,
    waldo: 115,
    mos: 85465,
    important: 'IMPORTANT' } ]
      + expected - actual

           "troiz": 0
           "waldo": 115
         }
         {
      -    "a": 0
      +    "a": 1
           "bar": 0
           "baz": 2
           "buzz": 4
           "fizz": 5

【问题讨论】:

标签: javascript typescript mocha.js diff chai


【解决方案1】:

据我所知,没有内置方法可以让 Chai 或 Mocha 生成差异,这些差异会添加到差异提供的上下文中,一些字段对测试失败不负责 .而且我不知道有什么扩展正是您正在寻找的。所以我只知道解决方法。


如果您将truncateThreshold 配置设置设置为更大的值,或者如果您不希望任何截断,则设置为0,出现在差异之前的失败消息将显示整个对象。因此,如果我将其添加到您的代码中:

chai.config.truncateThreshold = 0; // 0 means "don't truncate, ever".

(此documentation page 涵盖了配置选项。)

那么我得到的错误是:

      AssertionError: expected { a: 1,
  troiz: 0,
  bar: 0,
  baz: 2,
  poit: 3,
  narf: 4,
  fizzbuzz: 117,
  fizz: 5,
  buzz: 4,
  waldo: 115,
  mos: 85465,
  important: 'THIS IS IMPORTANT' } to deeply equal { a: 0,
  troiz: 0,
  bar: 0,
  baz: 2,
  poit: 3,
  narf: 4,
  fizzbuzz: 117,
  fizz: 5,
  buzz: 4,
  waldo: 115,
  mos: 85465,
  important: 'THIS IS IMPORTANT' }
      + expected - actual

       {
      -  "a": 1
      +  "a": 0
         "bar": 0
         "baz": 2
         "buzz": 4
         "fizz": 5

此外,在错误消息中获取自定义信息的一种方法是使用断言设置自定义消息,例如:

expect(actual).to.deep.equal(
            expected,
            `failed equality test on object with important field set to: ${actual.important}`)

自定义消息可以是您需要的详细或简洁。

如果只有一个字段对区分对象很重要,则自定义消息可能足以获取跟踪问题所需的信息。


对于对象数组,您可以通过遍历 actualexpected 数组并比较每个成员来执行比较。然后它基本上会像上面描述的那样工作。当然,这也有缺点:例如,如果第 1 项和第 10 项不同,您将仅获得第 1 项的报告,因为测试将以比较失败结束。当您修复此问题并再次运行测试时,您将获得第 10 项的报告。在实践中这是否是一个主要问题取决于您正在测试的数据类型。


在默认差异算法没有达到我想要的效果的情况下,我所做的一件事是导入我根据自己的喜好配置的差异库,然后使用该库在我关心的对象之间执行差异将结果组合成最终报告,然后使用断言进行检查。

同样,我不知道有一个库可以专门满足您的需求。但是,我可以想象遍历 actualexpected 数组以每对生成一个差异报告,然后将它们组合成一个包含识别信息的更大报告。

【讨论】:

【解决方案2】:

您可以在 mocha 命令中添加--inline-diffs,这将显示带有行号和内联差异的整个对象:

mocha --inline-diffs YourSpec.js

文档有点误导:https://mochajs.org/#diffs

【讨论】:

  • 当 mocha 作为库运行时(就像在 Postman 测试中一样) - 它仍然可能吗?
【解决方案3】:

由于所有反对票,请注意:我是 OP。我的预期解决方案不是解决我的架构决策的实际问题。有一个比较大对象的解决方案是一种代码味道。我已经重构了我的代码库,因此我不再需要这个尝试的解决方案了。


您正在尝试解决错误的问题。您想要的解决方案只是一种解决方法。

您的实际问题是首先要依赖于对大量巨大对象的深度比较。

您应该重构代码库以允许通过价格计算服务进行价格计算。使用简单的断言对服务进行单元测试很简单。

【讨论】:

    猜你喜欢
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多