web-dev-qa-db-fra.com

jasmin paramétré test unitaire

OK en tant que gars C # NUnit, cela pourrait être étrange.

Mais jasmine permet-il le test unitaire paramétré?

Je ne suis pas sûr si cela va à l'encontre de "déclarer" et "il" pour rendre les choses lisibles pour les non-programmeurs.

J'ai vu des plug-ins de tiers mais ils sont un peu vieux, je ne sais pas s'il a été ajouté à jasmine . Si je dois utiliser un plug-in

Juste pour aider ceux qui découvrent cela à l'avenir, on m'a dit sur le forum jasmine Il n'y a pas de support de première classe pour les tests paramétrés au sein de Jasmine même.

21
Ashley Kilgour

Basé sur la réponse de piotrek et l'article Test paramétré en Javascript , vous pouvez également utiliser l'approche suivante qui utilise la syntaxe ES6:

[
  ['abc', 3],
  ['ab', 2],
  ['', 0],
].forEach(([string, expectedLength]) => {
  it(`should return length ${expectedLength} for string "${string}"`, () => {
    expect(string.length).toBe(expectedLength);
  });
});

Je l'ai testé avec le framework de test Jest, mais cela devrait également fonctionner avec Jasmine.

28
Marco Eckstein

Meilleure solution (surtout si vous utilisez TypeScript)

Une autre solution consiste à utiliser Tableau d'objets à la place de Tableau de tableaux . Cela convient mieux si vous utilisez un système de frappe comme TypeScript.


Type de question

Imaginez que vous ayez le test paramétré suivant:

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

avec TypeScript, la compilation échouera, donnant deux erreurs:

erreur n ° 1:

erreur TS2345: argument de type 'nombre | boolean 'n'est pas assignable à un paramètre de type' boolean '.

erreur n ° 2: 

erreur TS2345: argument de type 'nombre | booléen 'n'est pas assignable au paramètre de type' numéro '. Le type 'vrai' n'est pas assignable au type 'numéro'.

En effet, TypeScript voit un tableau de ' nombre | booléen '.

Nous pourrions rapidement résoudre cet avertissement en utilisant une distribution explicite:

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

cependant cette solution n'est pas très agréable.


Solution

Une meilleure solution consiste à utiliser Tableau d'objets , afin que les types soient correctement gérés par défaut et qu'il n'y a pas besoin de de transtypage explicite :

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

Voulez-vous utiliser for au lieu de forEach (personnellement, je le trouve plus lisible)? C'est aussi possible:

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);
    }
 });
12
Francesco Borzi

je n'ai pas travaillé avec le jasmin depuis longtemps, mais il était assez facile d'ajouter des tests paramétrés:

  ['abc', 3,
   'ab',  4,
   '',    0].
it('should contain string length', function(string, expected){
   expect(string.length).toBe(expected);
});

avec seulement quelques lignes de code d'infrastructure:

Array.prototype.it = function(description, testCaseFunction) {
     _(this)
      .chunk(testCaseFunction.length)
      .each(function(innerArray){
                it(description + ' ' + JSON.stringify(innerArray), function(){
                   testCaseFunction.apply(this, innerArray);
                });     
      })
      .value();
};

en fonction de la syntaxe et de la volonté de modifier les objets js par défaut, vous disposez de nombreuses options: http://blog.piotrturski.net/2015/04/jasmine-parameterized-tests.html

3
piotrek

Alors j'ai commencé à combiner: 

  • YAML utilisant js-yaml
  • jasminejs
  • Manuscrit 

pour créer ce que je crois être des tests paramétrés lisibles comme ceci: 

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

Exécuter ceci donnera les résultats suivants: 

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.

Sources: https://github.com/deicongmbh/jasmine-param-tests

0
Dieter