且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在JavaScript中测试具有不同参数值的两个返回函数?

更新时间:2023-02-14 16:32:52

作为测试测试该功能的代码 非常 易碎,可能会折断,从而给您错误的提示否定:

Checking the code of the function as a test very brittle and can break easily giving you a false negative:

let someFn = function(a, b) {
  return a + b;
}

let expected = `function(a, b) {
  return a + b;
}`

console.log("Test original implementation:", test(someFn.toString(), expected));

//later the code style is changed to remove extra whitespace and make it one line
someFn = function(a, b) { return a+b; }

console.log("Test updated implementation:", test(someFn.toString(), expected));

//simple testing
function test(expected, actual) {
  return expected == actual
}

仅对代码进行非功能性更改会破坏测试.

Just making non-functional changes to the code breaks the test.

更糟糕的是,如果对代码进行了 功能更改,则该测试不能保证新实现的行为与旧实现相同,因为它仅查看代码的结构:

Worse yet, if there are functional changes to the code, the test cannot guarantee that the new implementation behaves like the old one, since it only looks at the structure of the code:

//simplified case of what the actual code could be doing
function someCodeBaseFunction() {
  let someInput = [8, 12, 42];
  return someFn(...someInput)
}

let someFn = function(a, b) { return a+b; }

let expected = `function(a, b) { return a+b; }`

console.log("Test original implementation:", test(someFn.toString(), expected));

console.log("Codebase usage:", someCodeBaseFunction()); //20, as the third number is ignored

//new implementation
someFn = function(...args) { 
  return args.reduce((a, b) => a + b); 
}

//update the test, so it passes
expected = `function(...args) { 
  return args.reduce((a, b) => a + b); 
}`

console.log("Test updated implementation:", test(someFn.toString(), expected));

//some existing line of code
console.log("Codebase usage:", someCodeBaseFunction()); //62, as the third number is now used

//simple testing
function test(expected, actual) {
  return expected == actual
};

相反,您要执行的操作将测试代码的行为并在此处设置您的期望.这样,如果实现发生更改,则可以确保实现仍然符合同一组期望.

Instead, what you want to do it test the behaviour of the code and set your expectations there. That way, if the implementation changes, you can make sure that the implementation still conforms to the same set of expectations.

在这种情况下,您需要创建一个示例输入,该输入最初是无序的,请尝试对其进行排序,然后期望该命令能够按预期工作.用伪代码看起来像这样:

In this case, you need to create a sample input that is initially unordered, try to order it and then expect that the order worked as you expected. In pseudo-code that would look a bit like this:

//arrange
input = [
 {testProperty: "c", id: 1},
 {testProperty: "a", id: 2},
 {testProperty: "d", id: 3},
 {testProperty: "b", id: 4}
];

expected = [
 {testProperty: "a", id: 2},
 {testProperty: "b", id: 4},
 {testProperty: "c", id: 1},
 {testProperty: "d", id: 3}
];

//act
input.sort(component.getComparisonFunction('testProperty'))

//assert
expect(input).toEqual(expected);

如果需要,还可以在更详细的级别上添加更多测试,以进一步约束期望.例如,如果您要确保比较区分大小写

You can also add more tests at a more granular level to bind the expectations even more, if you want. For example, if you want to ensure that the comparison is case-sensitive

//arrange
a = { testProperty: "a" };
b = { testProperty: "B" };

//act
result = component.getComparisonFunction('testProperty')(a, b)

//assert
expect(result).toBeGreaterThanOrEqual(1)

或不区分大小写:

//arrange
a = { testProperty: "a" };
b = { testProperty: "B" };

//act
result = component.getComparisonFunction('testProperty')(a, b)

//assert
expect(result).toBeLessThanOrEqual(-1)

这更加清晰地定义了您的期望,并确保将来的更改将完全满足您的需求.

This defines your expectations much more clearly and makes sure that future changes will cover exactly what you need.