web-dev-qa-db-ja.com

ジャスミンのパラメーター化された単体テスト

C#のNUnitの人としては、これは奇妙なことかもしれません。

しかし、ジャスミンはパラメーター化された単体テストを許可しますか?

プログラマー以外が読みやすくするための「宣言」や「それ」に反するかどうかはわかりません。

サードパーティのプラグインをいくつか見ましたが、ジャスミンに追加されたかどうかはわかりません。プラグインを使用する場合

将来的にこれを見つけた人を助けるためだけに、私はジャスミンフォーラムで知らされています。

25
Ashley Kilgour

piotrekの回答 および記事 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でも動作するはずです。

31
Marco Eckstein

より良い解決策(特にTypeScriptを使用する場合)

別の解決策は、Array of Arraysの代わりにArray of Objectsを使用することです。 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では、コンパイルに失敗して2つのエラーが発生します。

エラー#1:

エラーTS2345:タイプ 'numberの引数| boolean 'はタイプ' boolean 'のパラメーターに割り当てることができません。

エラー#2:

エラーTS2345:タイプ 'numberの引数| boolean 'は、タイプ' number 'のパラメーターに割り当てることができません。タイプ「true」はタイプ「number」に割り当てることができません。

TypeScriptが 'number | boolean'の配列を参照するためです。

明示的なキャストを使用して、この警告をすばやく解決できます。

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

または、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);
  });
}
23
Francesco Borzi

私は長い間ジャスミンを使っていませんが、パラメーター化されたテストを追加するのは非常に簡単でした。

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

3
piotrek

次の規則を使用すると、読みやすさが向上します。

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
3

だから私は組み合わせ始めました:

  • Js-yamlを使用したYAML
  • ジャスミン
  • TypeScript

私が信じているものを作成するには、このような読みやすいパラメータ化されたテストです:

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

0
Dieter