AAA: Das Testpattern im Detail

In dem Artikel Vergleich von MS Test und NUnit habe ich kurz das AAA-Pattern angerissen. Heute sehen wir uns das AAA-Pattern genauer an, warum man es nutzen sollte und welche Vorteile es bietet.
Die Grundstruktur
AAA steht für die drei Bereiche in einem Test: Assign, Act und Assert. Die Abschnitte definieren sich folgendermaßen:
- Assign: Erstellen der Instanzen und Mocks, um den Test ausführen zu können (Vorbereitung)
- Act: Ausführen der Aktion, die getestet wird (Durchführung)
- Assert: Prüfen der Ergebnisse, um die Aktion zu validieren (Prüfung)
In einer Testklasse sieht das Pattern folgendermaßen aus:
using Xunit;
public class CalculatorTest {
[Fact]
public void AddTest() {
// Assign
var sut = new Calculator();
// Act
var result = sut.Add(10, 20);
// Assert
Assert.Equal(30, result);
}
}
Anhand dieses Beispiels lässt sich die einfache Struktur schnell erkennen, egal ob man den Code kennt oder ihn zum ersten Mal sieht. Je nach Komplexität oder Länge des Tests bietet es sich an, die Parameter ebenfalls im ersten Block unterzubringen. Dies kann beispielsweise folgendermaßen aussehen:
using Xunit;
public class CalculatorTest {
[Fact]
public void AddTest() {
// Assign
var param1 = 10;
var param2 = 20;
var expectedResult = 30;
var sut = new Calculator();
// Act
var result = sut.Add(param1, param2);
// Assert
Assert.Equal(expectedResult, result);
}
}
Benamung und Struktur
In der Regel sorgen Standards dafür, dass Sachen einfacher werden und die kognitive Last geringer wird. Standards helfen uns beispielsweise in der Softwareentwicklung dabei, dass wir uns schneller in fremden Code zurechtfinden. Bei dem AAA-Pattern ist das nicht anders.
In Bezug auf das Codebeispiel 2 ist mir die explizite Definition von param1
, param2
und expectedResult
zu viel des Guten und etwas over-engineered. Bei Methoden, wo ein komplexer Datentyp übergeben wird, bietet
sich dieses Vorgehen eher an. Über den Namen paramX
lässt sich gerne streiten.
Nutzt hierfür vorzugsweise sprechendere Namen oder die Argumente der jeweiligen Methode :)
Was auch nicht unterschätzt werden sollte, ist der Name der Test-Instanz. Ich habe (leider) schon Tests gesehen, wo
der Name in den Tests (innerhalb der selben Testklasse) unterschiedlich war.
Was ich auch schwierig finde: Die Test-Instanz hat in jeder Testklasse einen anderen Namen.
Durch den nicht einheitlichen Namen ist es schwieriger auf den ersten Blick zu erkennen, welche der Variablen
getestet wird. Ich habe früher meine Test-Instanz immer target
genannt, weil es das “Ziel” ist, was ich
testen will. In verschiedenen Projekten habe ich auch schon instance
oder sut
(system under test) gesehen.
Persönlich bin ich über die Jahre zu einem Fan von sut
geworden. Zudem ist sut
ein übergreifender
Standardbegriff, wodurch auch fachfremde Abteilungen und Personen sich potentiell schneller zurechtfinden.
Auch für das Ergebnis der Aktion (sofern die Funktion einen Rückgabewert besitzt) bietet es sich an einen
Standardnamen zu verwenden. Über die Jahre nutze ich gerne result
, da ich es für sehr sprechend halte.
Die Kommentare im Code (Assign, Act, Assert) halte ich in der Regel für überflüssig. Eine Methode sollte immer kurz und lesbar sein, wie ein Buch. Bei komplexem Code, wo mehr vorbereitet werden muss, sind Kommentare empfehlenswert, um die Blöcke schneller zu erkennen. Ob ihr immer, manchmal oder nur bei Bedarf diese Kommentare schreibt, bleibt euch überlassen.
Abschlussworte
Der Aufbau des AAA-Pattern ist simpel gehalten und kann schnell ausprobiert und in einem aktuellen Projekt
umgesetzt werden. Meiner Meinung nach gehören AAA-Tests in jeden Werkzeugkasten eines Entwicklers.
Die Benamungen wie sut
oder result
sind ein Vorschlag meinerseits, um damit anzufangen.
Was ihr neben dem Pattern auf jeden Fall mitnehmen solltet: Besprecht eure Teststandards (Wie heißt die Testinstanz? Wie heißt der Rückgabewert?) im Team und einigt euch auf eine gemeinsame Struktur. Dieses Standards helfen euch schneller Tests zu schreiben, da der Name schon feststeht oder ihr Vorlagen in eurer IDE hinterlegen könnt, was euch Tipparbeit erspart. Falls ihr heterogene Projekte und Strukturen habt, könnte ein ADR für das Projekt sinnvoll sein.
Bildnachweis: Pixabay.com