Property-basiertes Testen in JavaScript: Finden Sie Bugs, die Sie nicht gesucht haben

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Was, wenn Tests sich selbst schreiben? Einführung in Property-based Testing

\n\n

Haben Sie jemals einen Unit-Test geschrieben, ihn ausgeführt, einen grünen Haken bekommen und einen Monat später einen Bug in derselben Funktion gefunden? Kommt Ihnen bekannt vor? Klassische Unit-Tests sind wie zu prüfen, ob Ihr Geldbeutel nicht leer ist, indem Sie nur auf einen einzigen Schein schauen. Sie überprüfen ein einziges konkretes Szenario, einen einzigen Satz von Eingabedaten. Was wäre, wenn ich Ihnen sage, dass es eine Möglichkeit gibt, den Computer dazu zu bringen, selbst Tausende verschiedener Szenarien zu erfinden und zu prüfen, ob Ihr Code nicht kaputt geht?

\n\n

Das ist keine Science-Fiction. Das ist Property-basiertes Testen in JavaScript (oder eigenschaftsbasiertes Testen). Anstatt zu schreiben „wenn man 2 und 3 übergibt, erhält man 5“, beschreiben Sie eine Eigenschaft (Property) Ihrer Funktion: „Für zwei beliebige Zahlen ist das Ergebnis der Addition eine Zahl, die immer größer oder gleich jeder der Summanden ist.“ Und die Testumgebung generiert hunderte zufällige Zahlenpaare und überprüft diese Behauptung.

\n\n

In diesem Artikel werden wir uns ansehen, wie Property-basiertes Testen funktioniert, wie es sich von gewöhnlichen Tests unterscheidet und wie Sie es mit der großartigen Bibliothek fast-check in Ihr Projekt integrieren können. Sie werden sehen, wie einfach es ist, „grenzwertige“ Bugs zu finden, nach denen Sie nicht einmal zu suchen gedacht hätten.

\n\n

Warum gewöhnliche Unit-Tests nicht immer retten?

\n\n

Kommen wir gleich zur Sache. Angenommen, Sie haben eine Funktion, die ein Zahlen-Array aufsteigend sortiert:

\n\n
function sortNumbers(arr) {\n  return arr.slice().sort((a, b) => a - b);\n}
\n\n

Sie schreiben einen Unit-Test:

\n\n
test('sortiert das Array [3, 1, 2]', () => {\n  expect(sortNumbers([3, 1, 2])).toEqual([1, 2, 3]);\n});
\n\n

Der Test ist grün. Sie sind glücklich. Aber was, wenn das Array null enthält? Oder undefined? Oder sehr große Zahlen? Oder ein Array mit 10.000 Elementen? Sie werden nicht für jeden dieser Fälle einen Test schreiben. Aber Property-basiertes Testen in JavaScript wird es tun.

\n\n

Anstatt Beispiele aufzuzählen, beschreiben Sie Invarianten (Eigenschaften), die immer wahr sein müssen:

\n
    \n
  1. Die Länge des sortierten Arrays ist gleich der Länge des ursprünglichen Arrays.
  2. \n
  3. Jedes Element des ursprünglichen Arrays ist im sortierten Array vorhanden.
  4. \n
  5. Für jeden Index i gilt, dass arr[i] <= arr[i+1].
  6. \n
\n\n

Genau diese Eigenschaften wird das Testen von Eigenschaften überprüfen.

\n\n

Die Bibliothek fast-check: Ihr Helfer beim Zufallstesten

\n\n

In der Welt von JavaScript ist das wichtigste Werkzeug für Property-based Testing fast-check. Es kann zufällige Daten aller Art generieren: Zahlen, Zeichenketten, Arrays, Objekte, Daten – und sogar komplexe Strukturen.

\n\n

Die Installation ist einfach:

\n
npm install fast-check --save-dev
\n\n

Jetzt schreiben wir unseren ersten Property-based Test für die Funktion sortNumbers. Wir verwenden das Framework Jest, aber fast-check funktioniert mit jedem Test-Runner.

\n\n
const fc = require('fast-check');\n\ntest('Sortieren erhält die Array-Länge', () => {\n  fc.assert(\n    fc.property(fc.array(fc.integer()), (arr) => {\n      const sorted = sortNumbers(arr);\n      return sorted.length === arr.length;\n    })\n  );\n});
\n\n

Was passiert hier? fc.array(fc.integer()) ist ein Generator, der zufällige Arrays mit zufälligen ganzen Zahlen erstellt. fc.property nimmt diesen Generator und überprüft die Behauptung (unsere Pfeilfunktion) mit 100 (standardmäßig) verschiedenen Datensätzen. Wenn auch nur ein Test fehlschlägt, wirft fc.assert einen Fehler und zeigt ein Gegenbeispiel an.

\n\n

Weitere Eigenschaften hinzufügen

\n\n

Eine Eigenschaft ist gut, aber drei sind besser. Lassen Sie uns überprüfen, ob das Array nach dem Sortieren tatsächlich geordnet ist:

\n\n
test('Sortieren gibt ein geordnetes Array zurück', () =>                

Blogs

Buchempfehlungen