Okay, als C # NUnit-Typ könnte das merkwürdig sein.
Aber erlaubt Jasmin einen parametrisierten Unit-Test?
Ich bin nicht sicher, ob es gegen das "Erklären" und "Es" verstößt, um die Dinge für Nicht-Programmierer lesbar zu machen.
Ich habe einige Plug-Ins von Drittanbietern gesehen, aber sie sind irgendwie alt, nicht sicher, ob sie zu Jasmin hinzugefügt wurden. Wenn ich ein Plug-In verwenden möchte
Um jedem zu helfen, der dies in der Zukunft findet, wurde mir auf dem Jasmin-Forum gesagt, dass es keine erstklassige Unterstützung für parametrisierte Tests in Jasmine selbst gibt.
Basierend auf piotreks Antwort und dem Artikel Parametrisierte Tests in Javascript können Sie auch den folgenden Ansatz verwenden, der die ES6-Syntax verwendet:
[
['abc', 3],
['ab', 2],
['', 0],
].forEach(([string, expectedLength]) => {
it(`should return length ${expectedLength} for string "${string}"`, () => {
expect(string.length).toBe(expectedLength);
});
});
Ich habe es mit dem Jest-Test-Framework getestet, aber es sollte auch mit Jasmine funktionieren.
Eine andere Lösung ist die Verwendung von Array of Objects anstelle von Array of Arrays . Es passt besser, wenn Sie ein Typsystem wie TypeScript verwenden.
Stellen Sie sich vor, Sie haben den folgenden parametrisierten Test:
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
});
});
mit TypeScript wird der Fehler nicht kompiliert und es werden zwei Fehler angezeigt:
fehler # 1:
fehler TS2345: Argument der Typnummer | boolean 'kann keinem Parameter des Typs' boolean 'zugewiesen werden.
fehler # 2:
fehler TS2345: Argument der Typnummer | boolean 'kann keinem Parameter vom Typ' number 'zugewiesen werden. Typ 'true' ist nicht Dem Typ 'number' zuweisbar.
Das liegt daran, dass TypeScript ein Array von ' number | sieht boolean '.
Wir könnten diese Warnung schnell lösen, indem wir einen expliziten Cast verwenden:
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
});
});
diese Lösung ist jedoch nicht sehr schön.
Ein besserer Weg ist die Verwendung von Array of Objects , sodass die Typen standardmäßig korrekt behandelt werden und keine explizite Umwandlung erforderlich ist :
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);
});
});
Möchten Sie for
anstelle von forEach
verwenden (finde ich persönlich lesbarer)? Das ist auch möglich:
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);
}
});
ich habe schon lange nicht mehr mit Jasmin gearbeitet, aber es war ziemlich einfach, parametrisierte Tests hinzuzufügen:
['abc', 3,
'ab', 4,
'', 0].
it('should contain string length', function(string, expected){
expect(string.length).toBe(expected);
});
mit nur wenigen Zeilen Infrastrukturcode:
Array.prototype.it = function(description, testCaseFunction) {
_(this)
.chunk(testCaseFunction.length)
.each(function(innerArray){
it(description + ' ' + JSON.stringify(innerArray), function(){
testCaseFunction.apply(this, innerArray);
});
})
.value();
};
abhängig von Ihrer gewünschten Syntax und der Bereitschaft, Standard-Js-Objekte zu ändern, haben Sie viele Optionen: http://blog.piotrturski.net/2015/04/jasmine-parameterized-tests.html
Sie können die folgende Konvention verwenden, um die Lesbarkeit zu verbessern:
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)
})
})
Folgende Testfälle werden ausgeführt:
Test Results
+ should be the same given: true and expected: true values
+ should be the same given: false and expected: false values
Also fing ich an zu kombinieren:
um zu schaffen, was meiner Meinung nach lesbare parametrisierte Tests sind:
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)
}
);
});
Wenn Sie dies ausführen, erhalten Sie folgende Ergebnisse:
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.