Den gleichen Mokka-Test mehrmals mit unterschiedlichen Daten ausführen

Lesezeit: 7 Minuten

Benutzeravatar von Tomás
Tomás

Problem

Ich habe mehrere Tests, die dasselbe in Mokka tun. Dies ist für mich eine Duplizierung und das Schlimmste, was Sie tun können, wenn Sie möchten, dass Ihr System wartbar ist.

var exerciseIsPetitionActive = function (expected, dateNow) {
    var actual = sut.isPetitionActive(dateNow);
    chai.assert.equal(expected, actual);
};

test('test_isPetitionActive_calledWithDateUnderNumSeconds_returnTrue', function () {
    exerciseIsPetitionActive(true, new Date('2013-05-21 13:11:34'));
});

test('test_isPetitionActive_calledWithDateGreaterThanNumSeconds_returnFalse', function () {
    exerciseIsPetitionActive(false, new Date('2013-05-21 13:12:35'));
});

Was brauche ich

Ich brauche eine Möglichkeit, meine duplizierten Mokka-Tests in nur einem zusammenzufassen.

Zum Beispiel in PhpUnit (und anderen Testframeworks) haben Sie Datenanbieter.
In phpUnit funktioniert ein DataProvider so:

<?php class DataTest extends PHPUnit_Framework_TestCase {
    /**
     * @dataProvider provider
     */
    public function testAdd($a, $b, $c)
    {
        $this->assertEquals($c, $a + $b);
    }

    public function provider()
    {
        return array(
          array(0, 0, 0),
          array(0, 1, 1),
          array(1, 0, 1),
          array(1, 1, 3)
        );
    }
}

Der Anbieter hier fügt Parameter in den Test ein, und der Test führt alle Fälle aus. Eignet sich perfekt für duplizierte Tests.

Ich möchte wissen, ob es in Mokka etwas Ähnliches gibt, zum Beispiel so etwas:

var exerciseIsPetitionActive = function (expected, dateNow) {
    var actual = sut.isPetitionActive(dateNow);
    chai.assert.equal(expected, actual);
};

@usesDataProvider myDataProvider
test('test_isPetitionActive_calledWithParams_returnCorrectAnswer', function (expected, date) {
    exerciseIsPetitionActive(expected, date);
});

var myDataProvider = function() {
  return {
      {true, new Date(..)},
      {false, new Date(...)}
  };
};

Was ich mir schon angeschaut habe

Es gibt eine Technik, die aufgerufen wird Geteilte Verhaltensweisen . Aber es löst das Problem nicht direkt mit einer Testsuite, sondern löst das Problem nur mit verschiedenen Komponenten, die duplizierte Tests haben.

Die Frage

Kennen Sie eine Möglichkeit, DataProvider in Mocha zu implementieren?

  • Ich liebe den Fragestil 🙂

    – Adam Matan

    4. November 2018 um 14:46 Uhr

  • Sehen Mokka-jeder.

    – Paul Razvan Berg

    28. März 2021 um 9:33 Uhr

Ein grundlegender Ansatz, um denselben Test mit unterschiedlichen Daten auszuführen, besteht darin, den Test in einer Schleife zu wiederholen, die die Daten bereitstellt:

describe('my tests', function () {
  var runs = [
    {it: 'options1', options: {...}},
    {it: 'options2', options: {...}},
  ];

  before(function () {
    ...
  });

  runs.forEach(function (run) {
    it('does sth with ' + run.it, function () {
      ...
    });
  });
});

before läuft, naja, vor allem its in a describe. Wenn Sie einige der Optionen in verwenden müssen before, unterlassen Sie fügen Sie es in die ein forEach Schleife, weil Mocha zuerst alle ausführen wird befores und die alle its, was wahrscheinlich nicht gewollt ist. Sie können entweder das Ganze setzen describe in der Schleife:

var runs = [
  {it: 'options1', options: {...}},
  {it: 'options2', options: {...}},
];

runs.forEach(function (run) {
  describe('my tests with ' + run.it, function () {
    before(function () {
      ...
    });

    it('does sth with ' + run.it, function () {
      ...
    });
  });
});

Wenn Sie Ihre Tests nicht mit mehreren verschmutzen möchten describes können Sie das umstrittene Modul verwenden sinon zu dieser sache:

var sinon = require('sinon');

describe('my tests', function () {
  var runs = [
    {it: 'options1', options: {...}},
    {it: 'options2', options: {...}},
  ];

  // use a stub to return the proper configuration in `beforeEach`
  // otherwise `before` is called all times before all `it` calls
  var stub = sinon.stub();
  runs.forEach(function (run, idx) {
    stub.onCall(idx).returns(run);
  });

  beforeEach(function () {
    var run = stub();
    // do something with the particular `run.options`
  });

  runs.forEach(function (run, idx) {
    it('does sth with ' + run.it, function () {
      sinon.assert.callCount(stub, idx + 1);
      ...
    });
  });
});

Sinon fühlt sich schmutzig an, ist aber effektiv. Mehrere Hilfsmodule wie Leche basieren auf Sinon, aber die Einführung weiterer Komplexität ist wohl nicht erforderlich.

  • Mein Linter zeichnet den foreach-Aufruf rot, es sei denn, ich verwende „// tslint:disable-next-line:mocha-no-side-effect-code“

    – cmzmuffin

    28. Oktober 2021 um 12:07 Uhr

Benutzeravatar von Kaizo
Kaizo

Mocha stellt dafür kein Tool zur Verfügung, aber es ist einfach, es selbst zu tun. Sie müssen die Tests nur innerhalb einer Schleife ausführen und die Daten mithilfe einer Closure an die Testfunktion übergeben:

suite("my test suite", function () {
    var data = ["foo", "bar", "buzz"];
    var testWithData = function (dataItem) {
        return function () {
            console.log(dataItem);
            //Here do your test.
        };
    };

    data.forEach(function (dataItem) {
        test("data_provider test", testWithData(dataItem));
    });
});

  • Das funktioniert bei mir nicht. Ich benutze die describe(), it() Syntax. Ist es wichtig, eine Testfunktion zurückzugeben, oder können wir den Test direkt in testWithData(dataItem) ?

    – svassr

    22. August 2014 um 13:22 Uhr


  • Ich musste sicherstellen, dass jedes zusätzliche Javascript (wie for each) ist in a it('tests', function(){ /*HERE */ }). Wie ich benutze it()Für jeden Test innerhalb der Schleife musste ich alles in a einwickeln describe(...). Ich endete mit einer Hierarchie describe > it > forEach > describe > itwodurch alle Tests in meiner Schleife am Ende meiner Tests erscheinen, egal wann es während des Tests auftritt, aber es funktioniert.

    – svassr

    22. August 2014 um 15:41 Uhr

  • können Sie einen Kern liefern it() und describe()?

    – Chovy

    13. April 2015 um 5:48 Uhr

  • Ich entschuldige mich, wenn dies nicht das richtige Forum ist, um diese Frage zu stellen, aber das scheint aus mehreren Gründen nicht zu funktionieren: – Mocha scheint keine “Suite”- oder “test(foo)”-Konstrukte zu haben – Benutze dies genau Code funktioniert nicht – es wird ein Fehler mit “Suite ist nicht definiert” ausgegeben. Wie wird behauptet, dass dies die Antwort ist? Versionen: Node 6.6.0, Mocha 3.1.2

    – Rubikon

    8. Dezember 2016 um 17:14 Uhr


  • @Rubicon Sie müssen die Tests mit der Schnittstelle “tdd” ausführen. Um das “bdd” zu verwenden, ändern Sie einfach “suite” für “describe” und “test” für “it”. Hier kannst du mehr darüber lesen: mochajs.org/#interfaces

    – Kaizo

    20. Dezember 2016 um 9:31 Uhr

Benutzeravatar von hashchange
Hashwechsel

Leche fügt Mocha diese Funktionalität hinzu. Siehe die Bekanntmachung und Dokumente.

Es ist besser, als einfach die Tests zu durchlaufen, denn wenn ein Test fehlschlägt, sagt es Ihnen, um welchen Datensatz es sich handelt.

Aktualisieren:

Ich mochte das Setup von Leche nicht und habe es nicht geschafft, es mit Karma zum Laufen zu bringen, also habe ich den Datenanbieter schließlich in a extrahiert separate Datei.

Wenn Sie es verwenden möchten, einfach schnapp dir die quelle. Dokumentation ist vorhanden in der Leche-Readmeund Sie finden zusätzliche Informationen und Verwendungstipps in der Datei selbst.

  • Leche ist am einfachsten zu verwenden. Danke für den Vorschlag.

    – Keyul

    18. Mai 2021 um 18:34 Uhr

Basierend auf der Antwort von @Kaizo habe ich mir Folgendes für meinen Test ausgedacht (es ist ein Controller, der einige Parameter aus der Anfrage erhält), um den Datenanbieter in PHPUnit zu emulieren. Das getParameters -Methode wird die Anfrage von Express empfangen und dann verwenden req.param um beispielsweise einige Abfrageparameter zu untersuchen, GET /jobs/?page=1&per_page=5. Dies zeigt auch, wie das Express-Request-Objekt gestubpt wird.

Hoffentlich kann es auch jemandem helfen.

// Core modules.
var assert = require('assert');

// Public modules.
var express = require('express');
var sinon = require('sinon');

// Local modules.
var GetJobs = require(__base + '/resources/jobs/controllers/GetJobs');

/**
 * Test suite for the `GetJobs` controller class.
 */
module.exports = {
    'GetJobs.getParameters': {
        'should parse request parameters for various cases': function () {
            // Need to stub the request `param` method; see http://expressjs.com/3x/api.html#req.param
            var stub = sinon.stub(express.request, 'param');
            var seeds = [
                // Expected, page, perPage
                [{limit: 10, skip: 0}],
                [{limit: 5, skip: 10}, 3, 5]
            ];
            var controller = new GetJobs();

            var test = function (expected, page, perPage) {
                stub.withArgs('page').returns(page);
                stub.withArgs('per_page').returns(perPage);

                assert.deepEqual(controller.getParameters(express.request), expected);
            };

            seeds.forEach(function (seed) {
                test.apply({}, seed);
            });
        }
    }
};

Der einzige Nachteil ist, dass Mocha die tatsächlichen Behauptungen nicht zählt (wie es PHPUnit tut), es wird nur als ein Test angezeigt.

Benutzeravatar von Chandana Kithalagama
Chandana Kithalagama

Eine einfachere Lösung wird im Folgenden mit beschrieben Mokka-Testdaten Bibliothek.

Beispiellösung für das Problem.

import * as assert from assert;
import { givenAsync } from mocha-testdata;

suite('My async test suite', function () {
  given([0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 3]).test('sum to 6', function (a, b, c) {
    assert.strictEqual(a + b + c, 6);
  });
});

Wenn Sie asynchrone Funktionsaufrufe testen müssen, was der häufigste Fall in der node.js-App ist, verwenden Sie stattdessen GivenAsync.

import * as assert from assert;
import { givenAsync } from mocha-testdata;

suite('My async test suite', function () {
  givenAsync([1, 2, 3], [3, 2, 1]).test('sum to 6', function (done, a, b, c) {
    doSomethingAsync(function () {
        assert.strictEqual(a + b + c, 6);
        done();
    });
  });
});

Benutzeravatar von Zachary Ryan Smith
Zachary Ryan Smith

Ich habe gefunden mokka-testcheck das einfachste Werkzeug dafür zu sein. Es generiert alle Arten von Daten. Es wird eingegrenzt, welche Eingabe dazu führt, dass Ihr Test fehlschlägt.

1404640cookie-checkDen gleichen Mokka-Test mehrmals mit unterschiedlichen Daten ausführen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy