茉莉参数化单元测试

问题描述 投票:21回答:5

好吧作为C#NUnit的家伙,这可能很奇怪。

但茉莉花是否允许参数化单元测试?

我不确定它是否违反“声明”和“它”以使非程序员可读。

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

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

unit-testing jasmine parameterized-unit-test parameterized-tests
5个回答
28
投票

基于piotrek's answer和文章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。


15
投票

Better solution (especially if you use TypeScript)

另一种解决方案是使用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
  });
});

但是这个解决方案并不是很好。


更好的方法是使用对象数组,因此默认情况下正确处理类型,不需要显式转换:

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);
    }
 });

3
投票

很久以来我没有使用茉莉花,但添加参数化测试很容易:

  ['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


1
投票

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

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

0
投票

所以我开始结合:

  • YAML使用js-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.

资料来源:https://github.com/deicongmbh/jasmine-param-tests

© www.soinside.com 2019 - 2024. All rights reserved.