Модульный тест с жасмином

Хорошо, как C# NUnit парень, это может быть странно.

Но разрешает ли жасмин параметризованный модульный тест?

Я не уверен, если это идет вразрез с "объявить" и "это", чтобы сделать вещи читаемыми для непрограммистов.

Я видел некоторые сторонние плагины, но они старые, не уверен, был ли он добавлен в жасмин. Если я собираюсь использовать плагин

Просто чтобы помочь любому, кто найдет это в будущем, мне сказали на форуме jasmine. Не существует первоклассной поддержки параметризованных тестов в самом Jasmine.

4 ответа

Основываясь на ответе Пиотрека и статье Параметризованное тестирование в 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.

Лучшее решение (особенно если вы используете 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: аргумент типа 'номер | логическое значение 'не присваивается параметру типа' число '. Тип 'true' не может быть назначен типу 'number'.

Это потому, что 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 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);
  });
});

Вы можете использовать следующее соглашение для повышения читабельности:

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

Я давно не работал с жасмином, но было довольно легко добавить параметризованные тесты:

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

Итак, я начал комбинировать:

  • YAML с использованием js-yaml
  • jasminejs
  • Машинопись

чтобы создать то, что я считаю читабельными параметризованными тестами, такими как это:

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

Другие вопросы по тегам