如何断言在单元测试中存在对象的子集?

时间:2020-10-06 21:38:20

标签: javascript mocha chai

所以我有很多嵌套的字符串列表。大嵌套列表最终将变得更大。但是我不希望大嵌套列表变大时更改单元测试。

我正在返回自定义错误和爵士乐。但这与这个问题无关。因此,我将其抽象为一系列水果。

我想要的是能够在不中断单元测试的情况下将项目添加到更大的列表中。换句话说,我想查看完整/干草堆/超集是否包含部分/针/子集。 (因此没有deepEquals)。我已经尝试了许多不同的方法来做到这一点,但我总是言不由衷。

摩卡规格文件

import "chai/register-assert";
import { assert } from "chai";

describe.only("Nested Lists and Objects", () => {
  let allFoodList = {
    smoothieStuff: ["apples", "bananas", "strawberries", "yogurt", "ice"],
    saladStuff: ["apples", "carrots", "spinach", "strawberries"],
    saladFruit: ["apples", "strawberries"],
  };

  let fruitList = {
    smoothieStuff: ["apples", "bananas", "strawberries"],
    saladStuff: ["apples", "strawberries"],
    saladFruit: ["apples", "strawberries"],
  };

  // None of these work
  it("deepNestedInclude", () => {
    assert.deepNestedInclude(allFoodList, fruitList);
  });
  it("deepInclude", () => {
    assert.deepInclude(allFoodList, fruitList);
  });
  it("include", () => {
    assert.include(allFoodList, fruitList);
  });
  it.skip("notInclude", () => {
    assert.notInclude(allFoodList, fruitList);
  });
  it("deepInclude", () => {
    assert.deepInclude(allFoodList, fruitList);
  });
  it.skip("notDeepInclude", () => {
    assert.notDeepInclude(allFoodList, fruitList);
  });
  it("nestedInclude", () => {
    assert.nestedInclude(allFoodList, fruitList);
  });
  it("deepNestedInclude", () => {
    assert.deepNestedInclude(allFoodList, fruitList);
  });
  it("ownInclude", () => {
    assert.ownInclude(allFoodList, fruitList);
  });
  it.skip("notOwnInclude", () => {
    assert.notOwnInclude(allFoodList, fruitList);
  });
  it("deepOwnInclude", () => {
    assert.deepOwnInclude(allFoodList, fruitList);
  });
  it.skip("notDeepOwnInclude", () => {
    assert.notDeepOwnInclude(allFoodList, fruitList);
  });
  it("sameMembers", () => {
    assert.sameMembers(allFoodList, fruitList);
  });
  it("sameDeepMembers", () => {
    assert.sameDeepMembers(allFoodList, fruitList);
  });
  it("includeMembers", () => {
    assert.include(allFoodList, fruitList);
  });
  it("includeDeepMembers", () => {
    assert.include(allFoodList, fruitList);
  });
});

摘要

  0 passing (22ms)
  4 pending
  12 failing

我跳过了“非”测试,因为它们也通过了不包含必需项目的测试。我也没有输入任何表示“有序”的内容,因为我敢肯定这是一个额外的约束。

2 个答案:

答案 0 :(得分:1)

您不能只使用一些辅助功能吗?:

?- allPrimes(100, Primes).
Primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97].

const isSubset = (haystack, needles) => needles .every (needle => haystack .includes (needle)) const allAreSubsets = (haystackObj, needleObj) => Object .keys (needleObj) .every (key => isSubset (haystackObj[key] || [], needleObj[key])) const allFoodList = { smoothieStuff: ["apples", "bananas", "strawberries", "yogurt", "ice"], saladStuff: ["apples", "carrots", "spinach", "strawberries"], saladFruit: ["apples", "strawberries"], } const fruitList = { smoothieStuff: ["apples", "bananas", "strawberries"], saladStuff: ["apples", "strawberries"], saladFruit: ["apples", "strawberries"], } const extraFruit = { smoothieStuff: ["apples", "bananas", "strawberries"], saladStuff: ["apples", "strawberries"], saladFruit: ["apples", "strawberries", "kiwis"], } console .log (allAreSubsets (allFoodList, fruitList)) console .log (allAreSubsets (allFoodList, extraFruit))仅告诉isSubset中的所有内容是否也位于needles中。 haystackallAreSubsets的每个属性执行相同的操作,将其与needlesObj的相同属性(如果不存在,则与空数组进行比较)。

包括类似的内容,您应该能够对布尔结果做出简单的断言。

答案 1 :(得分:0)

这不是我同意的答案,但是如果我没有更好的东西,这就是我要解决的答案。

我很感激Scott Sauyet's answer,但还不够。我知道我应该举一个更详细的例子,但我感到疲倦和沮丧。问题在于数组和对象可以嵌套得很深。我最终使用了递归函数。

对于如何使它变得更好/更强大,我乐于接受批评和建议。

说明:

  • 在try / catch块中说:“如果这些中的任何一个工作,返回true,我们就完成了。如果它们不起作用,则只能进行下一个比较。
  • 然后,如果涉及对象而不是数组,我们将遍历针的属性,并对针的每个属性进行类似的比较。
  • 当前不检查所有无限循环。一些。部分原因是我正在测试从API返回的JSON,因此对象中的循环引用并不是我要遇到的真正问题。但是"something"[0][0][0][0][0]确实存在。 "s"[0]==="s"
  • 如果不涉及任何对象,只需比较needle和haystack的松散相等性即可。如果它们相等,那就太好了。没错。

homebrew.assert.js

import { assert } from "chai";

function nestedInclude(haystack, needle, path) {
  try {
    assert.deepEqual(haystack, needle);
    return true;
  } catch {}
  try {
    assert.deepNestedInclude(haystack, needle);
    return true;
  } catch {}
  try {
    assert.includeDeepMembers(haystack, needle);
    return true;
  } catch {}
  if (typeof haystack === "object" || typeof needle === "object") {
    for (let key in needle) {
      let val = needle[key];
      if (val === needle) {
        throw new Error("We just entered an infinite loop.  Great.");
      }
      let subPath = path + "." + key;
      nestedInclude(haystack[key], needle[key], subPath);
    }
    return true;
  } else {
    assert.deepEqual(haystack, needle);
  }
}

export { nestedInclude };

export default {
  nestedInclude,
};

用法

import homebrew from "~/test/homebrew.assertion.js";

describe("...", ()=>{
  /* ... */
  it("...", ()=>{
    homebrew.nestedInclude(allFoodList, fruitList);
  });
});