End-to-End-Tests versus Unit-Tests, sollten Tests entkoppelt werden?

23

In unserem Unternehmen stellen wir normalerweise sicher, dass wir einen End-to-End-Test für unsere Websites / Web-Apps schreiben. Das heißt, wir greifen auf eine URL zu, füllen ein Formular aus, senden das Formular an eine andere URL und überprüfen die Ergebnisse der Seite. Wir tun dies, um die Formularvalidierung zu testen, um zu überprüfen, ob die HTML-Vorlagen die richtigen Kontextvariablen aufweisen usw.

Wir verwenden es auch, um die zugrunde liegende Logik indirekt zu testen.

Mir wurde von einem Mitarbeiter gesagt, dass der Grund dafür ist, dass wir die zugrunde liegende Implementierung jederzeit herausreißen und ändern können, solange die End-to-End-Tests erfolgreich sind.

Ich frage mich, ob diese Art der Entkopplung Sinn macht oder ob es nur eine Möglichkeit ist, das Schreiben von Tests für kleinere Codeeinheiten zu vermeiden.

Rudolf Olah
quelle
6
was told by a co-worker that the reason for this is that we can rip out and change the underlying implementation at any point as long as the end-to-end tests pass.- Das gilt auch für Unit-Tests. Es klingt für mich so, als würden die End-to-End-Tests als Entschuldigung dafür dienen, keine Komponententests zu schreiben.
Robert Harvey
12
Das gilt nicht für Unit-Tests. Das Ändern / Entfernen / Erstellen von Methoden oder Klassen erfordert die Aktualisierung aller Komponententests für diese Methoden oder Klassen. Nicht so bei End-to-End-Tests, es sei denn, die Funktionalität des Endbenutzers ändert sich. Solange es sich um einen Refactor auf Systemebene handelt (keine Änderung der Endbenutzerfunktionalität), sind keine Änderungen an den End-to-End-Tests erforderlich.
Dietbuddha
2
@dietbuddha, ich denke, das allgemeine Konzept gilt für Unit-Tests, aber in einem kleineren (Unit-) Umfang.
Sam

Antworten:

38

End-to-End-Tests sind ebenfalls erforderlich. Wie sonst können Sie wissen, dass Sie alle Einheiten korrekt miteinander verbunden haben? Mit sehr einfachem Code ist es möglich, alle Pfade durch den Code nur mit Ende-zu-Ende-Tests zu testen, aber je mehr Ebenen Sie erhalten, desto teurer wird dies in untragbarer Weise.

Angenommen, Sie haben drei Ebenen mit jeweils fünf möglichen Pfaden. Zum Testen aller Pfade durch die gesamte Anwendung sind 5 bis 3 End-to-End-Tests erforderlich. Sie können jedoch alle Pfade durch jede Einheit mit nur 5 bis 3 Einheitentests testen. Wenn Sie nur End-to-End-Tests durchführen, werden viele Pfade vernachlässigt, vor allem in Bezug auf Fehlerbehandlung und Randbedingungen.

Karl Bielefeldt
quelle
Das ist eine gute Antwort. Ich sehe den Wert von beidem, aber die Anzahl der Möglichkeiten zum vollständigen Testen aller Pfade mit End-to-End-Tests ist hilfreich, um zu erklären, warum Unit-Tests mehr durchgeführt werden müssen als es ist
Rudolf Olah
14
Ich sehe Unit-Tests vor allem deshalb als wertvoll an, weil sie Probleme schnell lokalisieren. End-to-End-Lösungen sind wertvoll, weil sie Ihnen die Gewissheit geben, dass alles zusammenarbeitet.
Jason Swett
20

Ja, End-to-End-Tests (oder Integrationstests) sind sehr sinnvoll, aber auch Komponententests. Idealerweise haben Sie beide, da beide in der Regel unterschiedliche Arten von Fehlern aufweisen. End-to-End-Tests sollten daher niemals eine Entschuldigung dafür sein, keine Komponententests durchzuführen.

Doc Brown
quelle
2
Eine kurze Anmerkung zur Formulierung; Auch wenn dies keine exakte Wissenschaft ist, werden viele Leute sagen, dass End-to-End-Tests und Integrationstests verschiedene Dinge sind. Siehe stackoverflow.com/questions/4904096/…
sbrattla
6

Nach einigen weiteren Jahren des Programmierens und Bearbeitens von Projekten werde ich eine Antwort auf meine eigene Frage geben.

Ja, Sie sollten Komponententests schreiben. End-to-End-Tests sind schwerer zu schreiben und brüchig, insbesondere wenn sie auf UI-Komponenten basieren.

Wenn Sie ein Framework wie Django oder Rails (oder Ihre eigenen benutzerdefinierten Klassen) verwenden, sollten Sie eine Formularklasse haben, die die Validierung des Formulars übernimmt. Sie haben auch Ansichtsklassen, die gerenderte Vorlagen und das Formular anzeigen und GET- und POST-Anforderungen verarbeiten.

In einem End-to-End-Test würden Sie:

  1. Holen Sie sich die URL
  2. Füllen Sie das Formular mit gültigen Daten aus
  3. Sende das Formular an die URL
  4. Stellen Sie sicher, dass die Datenbank aktualisiert oder eine Aktion aufgrund des gültigen Formulars ausgeführt wurde

Sie testen viel Code und Ihre Berichterstattung wird ziemlich gut sein, aber Sie testen nur den glücklichen Pfad, wenn alles richtig läuft. Wie stellen Sie sicher, dass das Formular die richtige Validierung enthält? Was ist, wenn dieses Formular auf mehreren Seiten verwendet wird? Schreiben Sie noch einen End-to-End-Test?

Versuchen wir es noch einmal mit Unit-Tests:

  1. Testen Sie die Methode view GET
  2. Testen Sie die View-POST-Methode mit einem Fake / Mock-Formular
  3. Testen Sie das Formular mit gültigen Daten
  4. Testen Sie das Formular mit ungültigen Daten
  5. Testen Sie die Nebenwirkungen des Formulars

Mit Unit-Tests testen Sie kleinere Codeteile, und die Tests sind spezifisch und einfacher zu schreiben. Wenn Sie dies mit TDD (Test Driven Development) kombinieren, erhalten Sie Code mit höherer Qualität.

Die Leichtigkeit, Unit-Tests zu schreiben, sollte nicht vernachlässigt werden, denn wenn Sie an einem Projekt arbeiten, für das es keine automatisierten Tests gibt, müssen Sie irgendwo anfangen. Das Starten mit Komponententests ist einfacher und schneller und ermöglicht es Ihnen, sofort nach Fehlern zu suchen, anstatt nur nach dem glücklichen Pfad.

Rudolf Olah
quelle
Ein weiterer Datenpunkt, Google Testing Blog, sagt Nein zu weiteren end2end-Tests: googletesting.blogspot.ca/2015/04/…
Rudolf Olah
5

Eigentlich sind End-to-End-Tests oder Integrationstests wichtiger als Unit-Tests, da sie sicherstellen, dass Sie ein voll funktionsfähiges System haben. Unit-Tests decken nicht den Integrationsteil eines Systems ab, was insbesondere bei großen Projekten eine komplizierte Aufgabe ist.

Wie bereits erwähnt, sollten Sie auch Unit-Tests durchführen, da es beim Integrationstest komplizierter ist, die Randfälle zu erfassen.

m3th0dman
quelle
1

Es überprüft das Systemverhalten, während Unit-Tests das Verhalten des Geräts überprüfen. Die Vorteile und Kosten sind unterschiedlich. Du könntest den einen oder den anderen oder beide machen.

Bei meiner Arbeit machen wir Acceptance Test Driven Development ohne Unit-Tests, was sich ähnlich anhört, wie Sie es beschrieben haben. Wir begannen mit beidem und machten im Laufe der Zeit Schluss mit Unit-Tests, um die Kosten zu senken, die die Vorteile für uns übersteigen.

Abgesehen davon denke ich, dass die Kosten / Nutzen für Ihre Problemdomäne und -umgebung die Entscheidungen für jede Entwicklungspraxis, einschließlich verschiedener automatisierter Testpraktiken, beeinflussen sollten. Ich bevorzuge es, dass alle Praktiken empirische Beweise im Kontext ihrer Verwendung haben, um sie zu sichern.

dietbuddha
quelle
Ich mache mir Sorgen, dass wir auf Akzeptanztests programmieren, die zu großen Klassen oder Methoden anstelle kleinerer Einheiten führen.
Rudolf Olah
@omouse: Nur weil Sie keine Komponententests schreiben, ist dies kein Grund, keinen guten Code zu schreiben. Wenn Sie jedoch unerfahrene Programmierer haben oder nur schlechte Gewohnheiten haben, können die Vorteile die Kosten überwiegen. In beiden Fällen sollten Sie die Analyse durchführen und auf eine einfache Gleichung reduzieren. For Any Practice: Practice iff Benefit > Cost
Dietbuddha