好吧,作为一个 C# NUnit 人,这可能很奇怪。
但是茉莉花允许参数化单元测试吗?
我不确定它是否违反“声明”和“它”以使非程序员可以阅读。
我见过一些第三方插件,但它们有点旧,不确定它是否已添加到 jasmine 中。如果我要使用插件
只是为了帮助将来发现这个问题的人,我在 jasmine 论坛上被告知 Jasmine 本身没有对参数化测试的一流支持。
好吧,作为一个 C# NUnit 人,这可能很奇怪。
但是茉莉花允许参数化单元测试吗?
我不确定它是否违反“声明”和“它”以使非程序员可以阅读。
我见过一些第三方插件,但它们有点旧,不确定它是否已添加到 jasmine 中。如果我要使用插件
只是为了帮助将来发现这个问题的人,我在 jasmine 论坛上被告知 Jasmine 本身没有对参数化测试的一流支持。
根据piotrek 的回答和文章Parameterized testing in Javascript,您还可以使用以下使用 ES6 语法的方法:
[
['abc', 3],
['ab', 2],
['', 0],
].forEach(([string, expectedLength]) => {
it(`should return length ${expectedLength} for string "${string}"`, () => {
expect(string.length).toBe(expectedLength);
});
});
我已经使用 Jest 测试框架对其进行了测试,但它也应该适用于 Jasmine。
另一种解决方案是使用Array of Objects而不是Array of Arrays。如果您使用 TypeScript 之类的打字系统,它会更合适。
假设您有以下参数化测试:
it('action(value) should reset the forms pool only if value is true', () => {
[
[true, 1],
[false, 0],
].forEach(([value, calledTimes]) => {
spyResetFormsPool.calls.reset();
component.action(value); // type error #1
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes); // type error #2
});
});
使用 TypeScript,它将无法编译并给出两个错误:
错误 #1:
错误 TS2345:“数字”类型的参数 | boolean' 不能分配给'boolean' 类型的参数。
错误 #2:
错误 TS2345:“数字”类型的参数 | boolean' 不能分配给'number' 类型的参数。类型 'true' 不能分配给类型 'number'。
那是因为 TypeScript 看到了一个 ' number | 布尔值'。
我们可以通过使用一些显式强制转换来快速解决这个警告:
it('action(value) should reset the forms pool only if value is true', () => {
[
[true, 1],
[false, 0],
].forEach(([value, calledTimes]) => {
spyResetFormsPool.calls.reset();
component.action(value as boolean); // necessary cast
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes as number); // necessary cast
});
});
但是这个解决方案不是很好。
更好的方法是使用Array of Objects,因此默认情况下可以正确处理类型,并且不需要显式转换:
it('action(value) should reset the forms pool only if value is true', () => {
[
{ value: true, calledTimes: 1 },
{ value: false, calledTimes: 0 },
].forEach(({ value, calledTimes }) => {
spyResetFormsPool.calls.reset();
component.action(value);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
});
});
你想使用for
而不是forEach
(我个人觉得它更具可读性)?这也是可能的:
it('action(value) should reset the forms pool only if value is true', () => {
for (const {value, calledTimes} of [
{value: true, calledTimes: 1},
{value: false, calledTimes: 0},
]) {
spyResetFormsPool.calls.reset();
component.action(value);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
}
});
或者,您也可以移动it
循环内部。当我这样做时,我通常会testId
为每个对象添加一个,这样我就可以跟踪哪些测试失败了:
for (const {value, calledTimes} of [
{ testId: 1, value: true, calledTimes: 1 },
{ testId: 2, value: false, calledTimes: 0 },
]) {
it(`action(value) should reset the forms pool only if value is true [${testId}]`, () => {
spyResetFormsPool.calls.reset();
component.action(value);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
});
}
您可以使用以下约定来提高可读性:
const testCases = [
{actualValue: true, expectedValue: true},
{actualValue: false, expectedValue: false}
]
testCases.forEach(({actualValue, expectedValue}) => {
it(`should be the same given: ${actualValue} and expected :${expectedValue} values`, () => {
expect(actualValue).toBe(expectedValue)
})
})
您将看到以下要运行的测试用例:
Test Results
+ should be the same given: true and expected: true values
+ should be the same given: false and expected: false values
我已经很久没有使用 jasmine 了,但是添加参数化测试很容易:
['abc', 3,
'ab', 4,
'', 0].
it('should contain string length', function(string, expected){
expect(string.length).toBe(expected);
});
只需几行基础设施代码:
Array.prototype.it = function(description, testCaseFunction) {
_(this)
.chunk(testCaseFunction.length)
.each(function(innerArray){
it(description + ' ' + JSON.stringify(innerArray), function(){
testCaseFunction.apply(this, innerArray);
});
})
.value();
};
根据您想要的语法和更改默认 js 对象的意愿,您有很多选择:http ://blog.piotrturski.net/2015/04/jasmine-parameterized-tests.html
所以我开始结合:
创建我认为可读的参数化测试,如下所示:
import YamlTableReader, {fixtureData, TestData} from "./YamlTableReader";
describe("TestSuite", () => {
describe("Real TestCase with Data Fixture", () => {
// now using tagged template-string to auto convert into YamlTableReader.
var testdata = fixtureData `
| ID | Value1 | Value2 | Squared |
| 0 |1 | 1 | 1 |
| 1 |2 | 2 | 4 |
| 2 |3 | 3 | 91 |
`;
// This actually creates a test for each row of the table above
testdata.describeEach("Square Test","[ID={ID}]:{Value1} x {Value2} should be equal to {Squared}",
(row: {Value1: number, Value2: number, Squared: number}) => {
expect((row.Value1 * row.Value2)).toBe(row.Squared)
}
);
});
运行它会得到以下结果:
Failures:
1) TestSuite 2 Real TestCase with Data Fixture Square Test : [ID=2]:3 x 3 should be equal to 91
Message:
Expected 9 to be 91.