Automatisierte Tests sind im Grunde nur Code, der einen Fehler auslöst, wenn dass etwas nicht stimmt. Die meisten Bibliotheken oder Test-Frameworks bieten eine Vielzahl von Primitiven, die das Schreiben von Tests erleichtern.
Wie im vorherigen Abschnitt erwähnt, enthalten diese Primitive fast immer ein Möglichkeit, unabhängige Tests (auch Testfälle genannt) zu definieren und Assertions an. Mit Assertions können Sie die Prüfung eines Ergebnisses wenn etwas nicht in Ordnung ist, und kann als Grundprimitiv aller Primitive testen.
Auf dieser Seite wird ein allgemeiner Ansatz für diese Primitive erläutert. Ihr ausgewähltes Framework wahrscheinlich so etwas, aber das ist keine genaue Referenz.
Beispiel:
import { fibonacci, catalan } from '../src/math.js';
import { assert, test, suite } from 'a-made-up-testing-library';
suite('math tests', () => {
test('fibonacci function', () => {
// check expected fibonacci numbers against our known actual values
// with an explanation if the values don't match
assert.equal(fibonacci(0), 0, 'Invalid 0th fibonacci result');
assert.equal(fibonacci(13), 233, 'Invalid 13th fibonacci result');
});
test('relationship between sequences', () => {
// catalan numbers are greater than fibonacci numbers (but not equal)
assert.isAbove(catalan(4), fibonacci(4));
});
test('bugfix: check bug #4141', () => {
assert.isFinite(fibonacci(0)); // fibonacci(0) was returning NaN
})
});
In diesem Beispiel wird eine Gruppe von Tests (manchmal auch als Suite bezeichnet) namens „Mathematik“ erstellt Tests“ und definiert drei unabhängige Testfälle, in denen jeweils einige Assertions ausgeführt werden. Diese Testläufe können in der Regel individuell angegangen oder durchgeführt werden, beispielsweise von einem Filter-Flag in Ihrem Test-Runner.
Assertion Helper als Primitive
Die meisten Test-Frameworks, einschließlich Vitest, enthalten eine Sammlung von Assertions
für ein assert
-Objekt verwenden, mit denen Sie schnell Rückgabewerte oder
anderen Bundesstaaten gegen eine Erwartung verstoßen. Diese Erwartung ist oft „als gut bekannt“
Werte. Im vorherigen Beispiel wissen wir, dass die 13. Fibonacci-Zahl
233, damit wir dies direkt mit assert.equal
bestätigen können.
Vielleicht haben Sie auch die Erwartung, dass ein Wert eine bestimmte Form oder größer als ein anderer Wert oder eine andere Eigenschaft haben. In diesem Kurs werden decken alle möglichen Assertion-Hilfsmittel ab, aber testen Sie Frameworks. sollten Sie immer mindestens die folgenden grundlegenden Prüfungen bereitstellen:
Eine „Wahrheit“ wird oft als „ok“ bezeichnet ob eine Bedingung erfüllt ist, wie Sie eine
if
schreiben, die prüft, ob etwas erfolgreich ist, richtig. Dies wird in der Regel alsassert(...)
oderassert.ok(...)
angegeben. enthält einen einzelnen Wert und einen optionalen Kommentar.Eine Gleichheitsprüfung, wie im mathematischen Testbeispiel, bei dem gibt den Wert oder Zustand eines Objekts zurück, der einem als funktionierend bekannten Wert entspricht. Diese sind für primitive Gleichheit (z. B. für Zahlen und Strings) oder referenzielle Gleichheit (sind dies dasselbe Objekt). Im Grunde sind dies nur eine „Wahrheit“ Häkchen setzen mit einem
==
- oder===
-Vergleich.- JavaScript unterscheidet zwischen lose (
==
) und strenger (===
) Gleichheit. Die meisten Testbibliotheken bieten Ihnen die Methodenassert.equal
undassert.strictEqual
.
- JavaScript unterscheidet zwischen lose (
Umfangreiche Gleichheitsprüfungen, die auch die Prüfung der Inhalte von Objekten, Arrays und anderen komplexeren Datentypen intern Logik, um Objekte zu durchsuchen und sie zu vergleichen. Diese sind wichtig, da es in JavaScript keine Möglichkeit gibt, zwei Objekten oder Arrays. Beispiel:
[1,2,3] == [1,2,3]
ist immer „false“. Testen Frameworks umfassen häufigdeepEqual
- oderdeepStrictEqual
-Hilfsmittel.
Assertion Helper, die zwei Werte vergleichen (anstatt nur eine Wahrheitsprüfung durchzuführen) mit zwei oder drei Argumenten:
- Der tatsächliche Wert, wie durch den zu testenden Code generiert oder der den zu überprüfen.
- den erwarteten Wert, in der Regel hartcodiert (z. B. eine Literalzahl oder String).
- Ein optionaler Kommentar, der beschreibt, was erwartet wurde oder was fehlgeschlagen sein könnte, die bei Ausfall dieser Zeile eingefügt wird.
Es ist auch üblich, Assertions zu kombinieren, um eine Vielzahl von da der Status Ihrer Website in seltenen Fällen für sich genommen hat. Beispiel:
test('JWT parse', () => {
const json = decodeJwt('eyJieSI6InNhbXRob3Ii…');
assert.ok(json.payload.admin, 'user should be admin');
assert.deepEqual(json.payload.groups, ['role:Admin', 'role:Submitter']);
assert.equal(json.header.alg, 'RS265')
assert.isAbove(json.payload.exp, +new Date(), 'expiry must be in future')
});
Vitest verwendet die Chai-Assertion-Bibliothek um intern ihre Assertion Helper zur Verfügung zu stellen. Es kann nützlich sein, um zu sehen, welche Assertions und Hilfsmethoden für Ihren Code geeignet sind.
Fließende und BDD-Assertions
Einige Entwickler bevorzugen einen Assertion-Stil, der als verhaltensgesteuert bezeichnet werden kann.
Entwicklung oder
Fließend
Assertions an. Diese werden auch als „erwarten“ bezeichnet. Helfer:innen, da der Einstiegspunkt für
zur Überprüfung der Erwartungen ist eine Methode mit dem Namen expect()
.
Erwarten, dass Hilfskräfte sich genauso verhalten wie Assertions, die als einfache Methode geschrieben wurden
Anrufe wie assert.ok
oder assert.strictDeepEquals
, aber einige Entwickler finden diese leichter zu lesen.
Eine BDD-Assertion könnte so aussehen:
// A failure here would generate "Expect result to be an array that does include 42"
const result = await possibleMeaningsOfLife();
expect(result).to.be.an('array').that.does.include(42);
// or a simpler form
expect(result).toBe('array').toContainEqual(42);
// the same in assert might be
assert.typeOf(result, 'array', 'Expected the result to be an array');
assert.include(result, 42, 'Expected the result to include 42');
Diese Art von Assertions funktionieren
aufgrund der Methodenverkettung,
wobei das von expect
zurückgegebene Objekt kontinuierlich mit
für weitere Methodenaufrufe. Einige Teile des Anrufs, darunter to.be
und that.does
im vorherigen Beispiel, haben keine Funktion und werden nur einbezogen, um den Aufruf durchzuführen.
einfacher zu lesen und möglicherweise einen automatisierten Kommentar zu generieren, wenn der Test
fehlgeschlagen. Hinweis: expect
unterstützt normalerweise keine optionalen Kommentare, weil
sollte der Fehler in der Verkettung klar beschrieben werden.)
Viele Test-Frameworks unterstützen sowohl Fluent/BDD als auch normale Assertions. Vitest Exportiert beispielsweise beide Chai hat einen etwas präziseren Ansatz für BDD. Schatz, enthält dagegen nur ein erwarten Methode standardmäßig.
Tests dateiübergreifend gruppieren
Beim Schreiben von Tests neigen wir bereits dazu, implizite Gruppierungen bereitzustellen, anstatt als alle Tests in einer Datei sind, schreiben Sie sie häufig für mehrere Dateien. Tatsächlich wissen Test-Runner normalerweise nur, dass eine Datei zu Testzwecken dient, eines vordefinierten Filters oder regulären Ausdrucks – Vitest beispielsweise enthält alle Dateien in Ihrem Projekt, die mit einer Endung wie „.test.jsx“ enden oder „.spec.ts“ („.test“ und „.spec“ plus eine Reihe gültiger Erweiterungen).
Komponententests befinden sich in der Regel in einer Peer-Datei mit der zu testenden Komponente. wie in der folgenden Verzeichnisstruktur:
<ph type="x-smartling-placeholder">Ebenso werden Einheitentests tendenziell neben dem zu testenden Code platziert. End-to-End-Tests können sich jeweils in einer eigenen Datei befinden, und Integrationstests können sogar eigenen Ordnern zugeordnet werden. Diese Strukturen können hilfreich sein, Bei komplexen Testläufen werden immer mehr eigene Dateien benötigt, die keine Test-Supportdateien sind, z. B. Supportbibliotheken, die nur für einen Test benötigt werden.
Tests innerhalb von Dateien gruppieren
Wie in vorherigen Beispielen verwendet, werden Tests üblicherweise innerhalb eines Aufrufs von
suite()
gruppiert, die Tests gruppiert, die Sie mit test()
eingerichtet haben. Suiten sind normalerweise nicht
Tests selbst testen, helfen aber, Struktur zu schaffen, indem sie verwandte Tests gruppieren
durch Aufrufen der übergebenen Methode. Für test()
beschreibt die übergebene Methode
die Aktionen des Tests selbst.
Wie bei Behauptungen gibt es in Fluent/BDD eine ziemlich Standard-Äquivalenz Gruppierungstests. Im folgenden Code werden einige typische Beispiele verglichen:
// traditional/TDD
suite('math tests', () => {
test('handle zero values', () => {
assert.equal(fibonacci(0), 0);
});
});
// Fluent/BDD
describe('math tests', () => {
it('should handle zero values', () => {
expect(fibonacci(0)).toBe(0);
});
})
In den meisten Frameworks verhalten sich suite
und describe
ähnlich, genau wie test
und
it
im Gegensatz zu den größeren Unterschieden zwischen expect
und assert
Assertions zu erstellen.
Andere Tools haben sehr unterschiedliche Ansätze zur Anordnung von Suiten und Tests. Für
Der integrierte Test-Runner von Node.js unterstützt das Verschachteln von Aufrufen von test()
zur
implizit eine Testhierarchie zu erstellen. Vitest lässt jedoch nur diese Art von
Verschachtelung mit suite()
und führt keine test()
aus, die in einem anderen test()
definiert ist.
Denken Sie wie bei Assertions daran, dass die genaue Kombination Methoden, die Ihr Technology Stack bietet, ist nicht so wichtig. In diesem Kurs geht es um aber Sie müssen herausfinden, wie sie sich auf Ihre die Wahl der Tools.
Lebenszyklusmethoden
Ein Grund dafür, Tests zu gruppieren, auch implizit auf der obersten Ebene innerhalb eines ist die Bereitstellung von Einrichtungs- und Teardown-Methoden, die für jeden Test ausgeführt werden. für eine Gruppe von Tests. Die meisten Frameworks bieten vier Methoden:
Für jeden `test()` oder `it()` | Einmal für die Suite | |
---|---|---|
Vor den Testläufen | „beforeEvery()“ | `beforeAll()` |
Nach den Testläufen | „afterEvery()“ | „afterAll()“ |
Sie können beispielsweise eine virtuelle Nutzerdatenbank vor jeder Datenbank und anschließend löschen:
suite('user test', () => {
beforeEach(() => {
insertFakeUser('bob@example.com', 'hunter2');
});
afterEach(() => {
clearAllUsers();
});
test('bob can login', async () => { … });
test('alice can message bob', async () => { … });
});
Dies kann nützlich sein, um Ihre Tests zu vereinfachen. Sie können gemeinsame Einrichtungs- und den Code zu löschen, anstatt ihn bei jedem Test zu duplizieren. Wenn der Parameter beim Einrichtungs- und Teardown-Code selbst einen Fehler aus, der auf strukturelles bei denen die Tests nicht fehlschlagen.
Allgemeine Empfehlungen
Hier sind ein paar Tipps, die du im Zusammenhang mit diesen Primitiven beachten solltest.
Primitiven dienen als Leitfaden
Denken Sie daran, dass die Tools und Primitive hier und auf den nächsten Seiten genau Vitest, Jest, Mocha, Web Test Runner oder einem anderen spezifisches Framework. Obwohl wir Vitest als allgemeiner Leitfaden verwendet haben, achten Sie darauf, das Framework Ihrer Wahl.
Assertions nach Bedarf kombinieren
Tests sind im Grunde Code, der Fehler auslösen kann. Jeder Läufer gibt
Primitiv, wahrscheinlich test()
, zur Beschreibung unterschiedlicher Testfälle.
Wenn dieser Runner jedoch auch assert()
, expect()
und Assertion-Assistenten bereitstellt,
Denken Sie daran, dass es hier mehr um Komfort geht. Sie können ihn überspringen,
die Sie brauchen. Sie können beliebigen Code ausführen, der zu einem Fehler führen könnte, einschließlich anderer
Assertion-Bibliotheken oder eine altmodische if
-Anweisung verwenden.
IDE-Einrichtung kann lebensretten
Dafür sorgen, dass Ihre IDE, z. B. VSCode, Zugriff auf die automatische Vervollständigung und
die Dokumentation zu den
gewählten Testtools, können Sie produktiver sein. Für
Beispiel: Es gibt über 100 Methoden für assert
in der Chai-Assertion
und eine Dokumentation für die
rechten Inline erscheinen, wäre das praktisch.
Dies kann besonders wichtig für einige Test-Frameworks sein, die globalen Namespace mit seinen Testmethoden. Das ist ein kleiner Unterschied, ist es oft möglich, Testbibliotheken zu verwenden, ohne sie zu importieren, wenn sie automatisch zum globalen Namespace hinzugefügt:
// some.test.js
test('using test as a global', () => { … });
Wir empfehlen, die Hilfsfunktionen zu importieren, auch wenn sie automatisch unterstützt werden.
denn das gibt Ihrer IDE eine klare Möglichkeit,
diese Methoden nachzuschlagen. (Möglicherweise haben Sie
ist beim Erstellen von React dieses Problem aufgetreten, da einige Codebasen eine magische
React
ist global, bei anderen jedoch nicht. Daher muss der Import in alle Dateien mit
React.)
// some.test.js
import { test } from 'vitest';
test('using test as an import', () => { … });