Was ist der beste Weg, um unsere Unit-Tests zu organisieren


18

Wir haben im Laufe der Jahre eine beträchtliche Anzahl von Komponententests für unser Hauptprogramm erstellt. Mehrere tausend. Das Problem ist, dass wir keine klare Vorstellung davon haben, welche Tests wir haben, weil es so viele gibt. Und das ist ein Problem, weil wir nicht wissen, wo wir bei Tests schwach sind (oder wo wir Duplikate haben).

Unsere App ist eine Berichts-Engine. Sie können also eine Vorlage erstellen, mit der Sie das Parsen testen (lesen Sie alle Tabelleneigenschaften), Daten zusammenführen (haben Sie bei der Zusammenführung die richtigen Tabelleneigenschaften beibehalten) und die letzte Seite formatieren (wird die Tabelle korrekt auf der Seite platziert) ) und / oder das Ausgabeformat (ist die erstellte DOCX-Datei korrekt).

Fügen Sie hinzu, was wir testen müssen. Nehmen Sie den Abstand zwischen den Tabellenzellen (wir verwenden Word, Excel und PowerPoint für das Berichtsdesign). Wir müssen den Seitenumbruch für eine Tabelle in einer Zelle, vertikal verbundene Zellen, horizontal verbundene Zellen, eine vertikal und horizontal verbundene Zelle testen, die eine Tabelle mit vertikal und horizontal verbundenen Zellen in der inneren Tabelle enthält, in der sich diese Tabelle befindet bricht über eine Seite.

In welche Kategorie fällt dieser Test? Tabellenauffüllung, Seitenumbrüche, verschachtelte Zellen, vertikal zusammengeführte Zellen, horizontal zusammengeführte Zellen oder etwas anderes?

Und wie dokumentieren wir diese Kategorien, benennen die Unit-Tests usw.?

Update: Eine Reihe von Personen hat vorgeschlagen, Abdeckungstools zu verwenden, um sicherzustellen, dass wir die vollständige Abdeckung haben. Leider ist dies in unserem Fall von begrenztem Nutzen, da die Fehler in der Regel auf bestimmte Kombinationen zurückzuführen sind, sodass der gesamte Code getestet wurde, jedoch nicht in dieser Kombination.

Zum Beispiel hatten wir gestern einen Kunden, der ein Word-Lesezeichen am Ende einer forEach-Schleife in seiner Vorlage (einem Word-Dokument) gestartet und am Anfang der nächsten forEach-Schleife beendet hat. Dies alles verwendete Code, für den Unit-Tests durchgeführt wurden, aber wir hatten nicht daran gedacht, dass die Kombination aus einer Vorlage, die ein Lesezeichen erweitert, 25-mal gestartet und dann 10-mal beendet werden sollte (die beiden forEach-Schleifen hatten eine unterschiedliche Anzahl von Zeilen).


1
Ihre Frage scheint wirklich zu sein: Woher wissen wir, dass wir ein bestimmtes Szenario getestet haben?
Andy Wiesendanger

Ja! Und wo sind die Tests für ähnliche Szenarien. Und daraus ergibt sich das zweitwichtigste Bedürfnis - das Lesen der behandelten Themen hilft uns, das zu finden, was wir verpasst haben.
David Thielen

Antworten:


13

Im Allgemeinen neige ich dazu, den Quellbaum für meine Komponententests zu spiegeln. Wenn ich also src / lib / fubar hätte, hätte ich einen Test / lib / fubar, der die Unit-Tests für fubar enthält.

Sie scheinen jedoch eher Funktionstests zu beschreiben. In diesem Fall hätte ich eine mehrdimensionale Tabelle, in der alle möglichen Bedingungen aufgeführt sind. Dann sind diejenigen, die keine Tests haben, entweder unsinnig oder benötigen einen neuen Test. Sie können sie dann natürlich in Gruppen von Testsuiten ablegen.


Wir spiegeln derzeit den Quellbaum. Wir haben aber zwei Probleme. Erstens gibt es für die Tabellenformatierung über 100 verschiedene Tests. Das Verfolgen dessen, was genau getestet wird, ist zu einem Problem geworden. Zweitens müssen sehr unterschiedliche Funktionsbereiche Tabellen testen - die Parser, die Datenersetzung, die Formatierung und die Erstellung des Ausgabedokuments. Ich denke, Sie haben Recht, in gewissem Sinne handelt es sich um eine Funktionsprüfung einer bestimmten Eigenschaft.
David Thielen

Was führt zu der Frage, wo wir die Testtabelle aufbewahren? Ich denke an eine Tabelle im Root-Quellverzeichnis?
David Thielen

Ich würde es in einer versionskontrollierten Tabelle im Testverzeichnis speichern . Wenn Sie eine Menge Dinge testen müssen, ist es von Vorteil, diese in Metastrukturen zu zerlegen. Versuchen Sie zu überlegen, was allgemein getestet wird, anstatt was oder wie.
Sardathrion - Wiedereinsetzung von Monica

7

Die gebräuchlichste Struktur scheint der srcund test-Verzeichnisspiegel zu sein.

src/module/class
test/module/class_test

Es gibt jedoch eine alternative Struktur, die ich gesehen habe und die ich jetzt für besser halte.

src/module/class
src/module/class_test

Da Unit-Tests in der Regel die Klasse widerspiegeln, die sie testen, können Sie durch Platzieren in demselben Verzeichnis viel einfacher auf die Dateien zugreifen, sodass Sie nebeneinander arbeiten können.


2
Ein Nachteil des vorherigen Ansatzes ist, dass Sie jedes Mal, wenn Sie die Dateistruktur des Projekts ändern, dasselbe für die Teststruktur tun müssen. Dieses Problem tritt nicht auf, wenn sich der Code in den Tests befindet.
Victor175

5

In .NET neige ich dazu, die Namespace-Struktur für den Quellcode in den Testprojekten unter einem Master-Namespace "Tests.Unit" oder "Tests.Integration" zu spiegeln oder zumindest zu approximieren. Alle Komponententests finden in einem Projekt statt, wobei die Grundstruktur des Quellcodes als Ordner innerhalb des Projekts repliziert wird. Gleiches gilt für Integrationstests. Eine einfache Lösung für ein Projekt könnte also so aussehen:

Solution
   MyProduct.Project1 (Project)
      Folder1 (Folder)
         ClassAA (Class def)
         ...
      Folder2
         ClassAB
         ...
      ClassAC
      ...
   MyProduct.Project2
      Folder1
         ClassBA
         ...
      ClassBB
      ...
   ...
   MyProduct.Tests.Unit
      Project1
         Folder1
            ClassAATests
            ClassAATests2 (possibly a different fixture setup)
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests
      ...
   MyProduct.Tests.Integration
      Project1 (a folder named similarly to the project)
         Folder1 (replicate the folders/namespaces for that project beneath)
            ClassAATests
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests

Für alle AATs oder AEETs, die mit einem Unit-Testing-Framework codiert sind, ändert sich dies ein wenig. In der Regel spiegeln diese Tests eine Reihe von Schritten wider, mit denen die Funktionalität eines neuen Anwendungsfalls oder einer neuen Story getestet wird. Normalerweise strukturiere ich diese Tests in einem MyProduct.Tests.AcceptanceProjekt als solches, mit Tests für jede Geschichte, möglicherweise gruppiert nach Meilenstein oder "epischer" Geschichte, zu der die zu entwickelnde Geschichte gehörte. Dies sind jedoch wirklich nur Überintegrationstests. Wenn Sie es also vorziehen, die Tests eher objektorientiert als geschichtenorientiert zu strukturieren, benötigen Sie nicht einmal ein MyProduct.Tests.Acceptanceoder ein ähnliches Projekt. Werfen Sie sie einfach in MyProduct.Tests.Integrationden Bereich des Prüflings der höchsten Ebene.


3

Es gibt keinen Grund, einen Komponententest nur in einer Kategorie durchzuführen. Alle wichtigen Unit-Test-Toolkits unterstützen die Erstellung von Testsuiten , die Tests für eine bestimmte Kategorie bündeln. Wenn ein bestimmter Codebereich geändert wurde, sollte der Entwickler zuerst diese Suite ausführen und häufig feststellen, was fehlerhaft ist. Wenn ein Test betrifft Polsterung und Pausen und Verschachtelung, mit allen Mitteln stecken es in alle drei Suiten.

Das heißt, Unit-Tests müssen immer ausgeführt werden, dh sie sollten klein und schnell genug sein, damit sie alle ausgeführt werden können, bevor Code übergeben wird. Mit anderen Worten, es spielt keine Rolle, in welcher Kategorie sich ein Test befindet, er sollte trotzdem ausgeführt werden, bevor er festgeschrieben wird. Suiten sind eigentlich nur eine Krücke, die Sie benutzen, wenn Sie aus irgendeinem Grund keine Tests schreiben können, die so schnell sind, wie sie sollten.

In Bezug auf die Abdeckung gibt es sehr gute Abdeckungstools, mit denen Sie feststellen können, wie viel Prozent der Zeilen tatsächlich durch die Ausführung Ihrer Tests beansprucht wurden. Dies ist ein offensichtlicher Hinweis darauf, welche Art von Tests Ihnen noch fehlen.

In Bezug auf die Benennung gibt es keinen besonderen Wert für den Aufwand für die Namen von Komponententests. Alles, was Sie von Ihren Tests hören möchten, ist "5235 von 5235 Tests bestanden". Wenn ein Test fehlschlägt, lesen Sie nicht den Namen, sondern die Meldung , z. B. die assert()Zeichenfolge in der , die Ihr Erfolgskriterium implementiert. Die Nachricht sollte informativ genug sein, damit Sie eine Vorstellung davon haben, was falsch ist, ohne den Testkörper zu lesen. Der Name ist im Vergleich dazu unwichtig.


Stimmen Sie zu 100% Ihren Aussagen zu (unsere Build-Maschine führt alle Tests beim Einchecken durch). Unser großes Problem ist es zu verfolgen, was wir testen. Und Code-Coverage ist keine große Hilfe (siehe Update oben).
David Thielen

1

Eine Möglichkeit, festzustellen, ob Sie in Bezug auf Tests schwach sind, ist die Rückverfolgbarkeit. In der Regel für Tests erfolgt dies in Form einer Abdeckung.

Ziel ist es, zu messen, welche Codeteile von Ihren Tests ausgeübt werden, damit Sie Code sehen können, der nicht von Ihren Tests abgedeckt wird. Es liegt an Ihnen (und dem Coverage-Tool), zu definieren, was ein "Teil des Codes" ist. Das Mindeste ist die Zweigabdeckung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.