Unit testing jasmine参数化单元测试

Unit testing jasmine参数化单元测试,unit-testing,jasmine,parameterized-unit-test,parameterized-tests,Unit Testing,Jasmine,Parameterized Unit Test,Parameterized Tests,好吧,作为一个C#NUnit人,这可能很奇怪 但是jasmine允许参数化单元测试吗 我不确定这是否违背了“声明”和“它”的要求,使非程序员能够阅读 我见过一些第三方插件,但它们有点旧,不确定是否已添加到jasmine中。 如果我需要使用插件 为了帮助将来发现这一点的人,我在jasmine论坛上被告知,jasmine本身没有对参数化测试的一流支持。我很久没有使用jasmine了,但是添加参数化测试非常容易: ['abc',3, “ab”,4, '', 0]. 它('应包含字符串长度')函数

好吧,作为一个C#NUnit人,这可能很奇怪

但是jasmine允许参数化单元测试吗

我不确定这是否违背了“声明”和“它”的要求,使非程序员能够阅读

我见过一些第三方插件,但它们有点旧,不确定是否已添加到jasmine中。 如果我需要使用插件


为了帮助将来发现这一点的人,我在jasmine论坛上被告知,jasmine本身没有对参数化测试的一流支持。

我很久没有使用jasmine了,但是添加参数化测试非常容易:

['abc',3,
“ab”,4,
'',    0].
它('应包含字符串长度')函数(字符串,应为){
expect(string.length).toBe(expected);
});
只需几行基础架构代码:

Array.prototype.it=函数(描述,testCaseFunction){
_(本)
.chunk(testCaseFunction.length)
.each(函数(内部数组){
它(description+''+JSON.stringify(innerArray),function(){
apply(这个,innerArray);
});     
})
.value();
};
根据您想要的语法和更改默认js对象的意愿,您有很多选择:

基于和本文,您还可以使用以下使用ES6语法的方法:

[
[abc',3],
[ab',2],
['', 0],
].forEach(([string,expectedLength])=>{
它(`应该为字符串“${string}”返回长度${expectedLength},`,()=>{
expect(string.length).toBe(expectedLength);
});
});
我已经用Jest测试框架对其进行了测试,但它也应该与Jasmine一起使用。

更好的解决方案(特别是如果使用TypeScript) 另一种解决方案是使用对象数组,而不是数组。如果你使用像TypeScript这样的打字系统,它会更适合你


类型问题 假设您有以下参数化测试:

it('仅当值为true时,操作(值)才应重置表单池',()=>{
[
[对,1],
[错误,0],
].forEach(([value,calledtime])=>{
spyResetFormsPool.calls.reset();
component.action(value);//类型错误#1
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);//类型错误#2
});
});
使用TypeScript时,它将无法编译,并出现两个错误:

错误#1:

错误TS2345:类型为“number | boolean”的参数不能分配给类型为“boolean”的参数

错误#2:

错误TS2345:类型为“number | boolean”的参数不能分配给类型为“number”的参数。类型“true”不正确 可分配给类型“number”

这是因为TypeScript看到一个“数字|布尔值””数组

我们可以通过使用一些显式强制转换快速解决此警告:

it('仅当值为true时,操作(值)才应重置表单池',()=>{
[
[对,1],
[错误,0],
].forEach(([value,calledtime])=>{
spyResetFormsPool.calls.reset();
action(值为布尔值);//必要的强制转换
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes as number);//必要的强制转换
});
});
然而,这个解决方案不是很好


解决方案 更好的方法是使用对象数组,这样默认情况下可以正确处理类型,无需显式转换

it('仅当值为true时,操作(值)才应重置表单池',()=>{
[
{value:true,calledTime:1},
{value:false,调用时间:0},
].forEach({value,calledTimes})=>{
spyResetFormsPool.calls.reset();
成分、作用(价值);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
});
});

您想使用
for
而不是
forEach
(我个人觉得它更可读)吗?这也是可能的:

it('仅当值为true时,操作(值)才应重置表单池',()=>{
for的(const{value,calledTimes}[
{value:true,calledTime:1},
{value:false,调用时间:0},
]) {
spyResetFormsPool.calls.reset();
成分、作用(价值);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
}
});
或者,您也可以在循环内移动
it
。执行此操作时,我通常会向每个对象添加一个
testId
,以便跟踪哪些测试失败:

的(const{value,calledTimes})的
[
{testId:1,value:true,calledTime:1},
{testId:2,value:false,calledTime:0},
]) {
它(`action(value)应该只在value为true[${testId}]时重置表单池`,()=>{
spyResetFormsPool.calls.reset();
成分、作用(价值);
expect(spyResetFormsPool).toHaveBeenCalledTimes(calledTimes);
});
}

所以我开始组合:

  • 使用jsyaml的YAML
  • 茉莉花
  • 打字稿
要创建我认为可读的参数化测试,请执行以下操作:

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.

来源:

您可以使用以下约定来提高可读性:

const测试用例=[
{actualValue:true,expectedValue:true},
{actualValue:false,expectedValue:false}
]
forEach({actualValue,expectedValue})=>{
它(`应该是相同的,给定:${actualValue}和期望:${expectedValue}值',()=>{
expect(实际值).toBe(预期值)
})
})
您将看到要运行的以下测试用例:

Test Results
+ should be the same given: true and expected: true values
+ should be the same given: false and expected: false values

你可以把你在茉莉花论坛上找到的答案贴出来作为你自己问题的答案,并接受它。应该补充的是,如果你在每个街区前都有一个答案,可能在每个街区后都有一个答案,那么这个答案就完全打破了。如果您尝试使用beforeEach块Jest以这种方式设置测试,则会抛出一个“TypeError:无法正确读取”