Ausgelöst von diesem Thread denke ich (wieder) darüber nach, endlich Unit-Tests in meinen Projekten zu verwenden. Ein paar Plakate dort sagen so etwas wie "Tests sind cool, wenn sie gute Tests sind". Meine Frage jetzt: Was sind "gute" Tests?
In meinen Anwendungen ist der Hauptteil häufig eine Art numerische Analyse, die von großen Mengen beobachteter Daten abhängt und zu einer Anpassungsfunktion führt, mit der diese Daten modelliert werden können. Ich fand es besonders schwierig, Tests für diese Methoden zu erstellen, da die Anzahl der möglichen Eingaben und Ergebnisse zu groß ist, um jeden Fall zu testen, und die Methoden selbst oft recht langwierig sind und nicht ohne weiteres überarbeitet werden können, ohne die Leistung zu beeinträchtigen. Ich interessiere mich besonders für "gute" Tests für diese Art von Methode.
quelle
Antworten:
Die Kunst des Einheitentests sagt Folgendes über Einheitentests aus:
und später wird hinzugefügt, dass es vollständig automatisiert, vertrauenswürdig, lesbar und wartbar sein sollte.
Ich würde Ihnen wärmstens empfehlen, dieses Buch zu lesen, wenn Sie es noch nicht getan haben.
Meiner Meinung nach sind all diese sehr wichtig, aber die letzten drei (vertrauenswürdig, lesbar und wartbar) sind besonders wichtig, als ob Ihre Tests diese drei Eigenschaften haben, und Ihr Code hat sie normalerweise auch.
quelle
It should run at the push of a button
dies, dass für einen Komponententest weder Container (App-Server) ausgeführt werden müssen (für das zu testende Gerät), noch eine Ressourcenverbindung (z. B. DB, externe Webdienste usw.)? Ich bin nur verwirrt, welche Teile einer Anwendung Unit-getestet werden sollen und welche nicht. Mir wurde gesagt, dass Unit-Tests nicht von der DB-Verbindung und der Ausführung von Containern abhängen sollten, sondern stattdessen möglicherweise Mockups verwenden sollten.Ein guter Komponententest spiegelt nicht die Funktion wider, die er testet.
Nehmen wir als stark vereinfachtes Beispiel an, Sie haben eine Funktion, die einen Durchschnitt von zwei ints zurückgibt. Der umfassendste Test würde die Funktion aufrufen und prüfen, ob ein Ergebnis tatsächlich ein Durchschnitt ist. Das macht überhaupt keinen Sinn: Sie spiegeln (replizieren) die Funktionalität, die Sie testen. Wenn Sie in der Hauptfunktion einen Fehler gemacht haben, werden Sie im Test den gleichen Fehler machen.
Mit anderen Worten, wenn Sie feststellen, dass Sie die Hauptfunktionen im Komponententest replizieren, ist dies wahrscheinlich ein Zeichen dafür, dass Sie Ihre Zeit verschwenden.
quelle
Gute Komponententests sind im Wesentlichen die Angaben in ausführbarer Form:
Ich habe festgestellt, dass Test-Driven-Development für Bibliotheksroutinen sehr gut geeignet ist, da Sie im Wesentlichen zuerst die API und dann die eigentliche Implementierung schreiben.
quelle
Bei TDD testet "gut" die Testfunktionen , die der Kunde wünscht . Features müssen nicht unbedingt Funktionen entsprechen, und Testszenarien sollten vom Entwickler nicht im luftleeren Raum erstellt werden
In Ihrem Fall - ich vermute - besteht das "Merkmal" darin, dass die Anpassungsfunktion die Eingabedaten innerhalb einer bestimmten Fehlertoleranz modelliert. Da ich keine Ahnung habe, was Sie wirklich tun, denke ich mir etwas aus. hoffentlich ist es anal.
Beispielgeschichte:
Sie sprechen also mit den Piloten (und mit dem Zielcomputer, falls dieser empfindungsfähig ist). Sprechen Sie zuerst über das, was "normal" ist, und dann über das Anormale. Sie erfahren, worauf es in diesem Szenario wirklich ankommt, was gemeinsam ist, was unwahrscheinlich ist und was nur möglich ist.
Angenommen, Sie haben normalerweise ein halbes Sekundenfenster über sieben Telemetriedatenkanäle: Geschwindigkeit, Neigung, Wanken, Gieren, Zielvektor, Zielgröße und Zielgeschwindigkeit. Diese Werte sind konstant oder ändern sich linear. Normalerweise haben Sie weniger Kanäle und / oder die Werte ändern sich schnell. Also zusammen kommen Sie mit einigen Tests auf wie:
Jetzt haben Sie vielleicht bemerkt, dass es für die in der Geschichte beschriebene Situation kein Szenario gibt. Es stellte sich heraus, dass das Ziel in der ursprünglichen Geschichte nach einem Gespräch mit dem Kunden und anderen Interessengruppen nur ein hypothetisches Beispiel war. Die wirklichen Tests ergaben sich aus der anschließenden Diskussion. Das kann passieren. Die Geschichte sollte umgeschrieben werden, muss es aber nicht sein [da die Geschichte nur ein Platzhalter für ein Gespräch mit dem Kunden ist].
quelle
Erstellen Sie Tests für Eckfälle, z. B. ein Testset, das nur die Mindestanzahl von Eingaben (1 oder 0 möglich) und einige Standardfälle enthält. Diese Komponententests sind kein Ersatz für gründliche Abnahmetests und sollten es auch nicht sein.
quelle
Ich habe viele Fälle erlebt, in denen sich die Leute sehr viel Mühe geben, Tests für Code zu schreiben, der selten eingegeben wird, und keine Tests für Code, der häufig eingegeben wird.
Bevor Sie sich hinsetzen, um Tests zu schreiben, sollten Sie sich eine Art Anrufdiagramm ansehen, um sicherzustellen, dass Sie eine angemessene Abdeckung planen.
Außerdem glaube ich nicht daran, Tests zu schreiben, nur um zu sagen "Ja, das testen wir". Wenn ich eine Bibliothek verwende, die abgelegt wird und unveränderlich bleibt, werde ich keinen Tag damit verschwenden, Tests zu schreiben, um sicherzustellen, dass die Innereien einer API, die sich niemals ändern wird, wie erwartet funktionieren, auch wenn bestimmte Teile davon punkten hoch in einem Call-Diagramm. Tests, die diese Bibliothek (meinen eigenen Code) verwenden, weisen darauf hin.
quelle
Nicht ganz so TDD, aber nachdem Sie sich mit der Qualitätssicherung befasst haben, können Sie Ihre Tests verbessern, indem Sie Testfälle einrichten, um alle Fehler zu reproduzieren, die während des Qualitätssicherungsprozesses auftreten. Dies kann besonders nützlich sein, wenn Sie längerfristigen Support in Anspruch nehmen und an einen Ort gelangen, an dem Sie das Risiko eingehen, dass andere versehentlich alte Bugs wieder einführen. Es ist besonders wertvoll, einen Test zu haben, um dies zu erfassen.
quelle
Ich versuche bei jedem Test nur eines zu testen. Ich versuche, jedem Test einen Namen wie shouldDoSomething () zu geben. Ich versuche das Verhalten zu testen, nicht die Implementierung. Ich teste nur öffentliche Methoden.
Normalerweise habe ich einen oder mehrere Tests für den Erfolg und dann vielleicht eine Handvoll Tests für das Scheitern nach öffentlicher Methode.
Ich benutze viel Mock-ups. Ein gutes Mock-Framework wie PowerMock wäre wahrscheinlich sehr hilfreich. Obwohl ich noch keine benutze.
Wenn Klasse A eine andere Klasse B verwendet, würde ich eine Schnittstelle X hinzufügen, damit A B nicht direkt verwendet. Dann würde ich ein XMockup-Modell erstellen und es in meinen Tests anstelle von B verwenden. Es hilft wirklich, die Testausführung zu beschleunigen, die Testkomplexität zu reduzieren und die Anzahl der Tests zu verringern, die ich für A schreibe, da ich nicht mit den Besonderheiten von B fertig werden muss. Ich kann beispielsweise testen, dass A X.someMethod () aufruft. anstelle eines Nebeneffekts beim Aufrufen von B.someMethod ().
Halten Sie auch Ihren Testcode sauber.
Wenn Sie eine API wie eine Datenbankebene verwenden, verspotten Sie diese und aktivieren Sie das Modell, um bei jeder möglichen Gelegenheit auf Befehl eine Ausnahme auszulösen. Ich führe dann die Tests ein, ohne zu werfen, und das in einer Schleife, wobei jedes Mal eine Ausnahme bei der nächsten Gelegenheit geworfen wird, bis der Test erneut erfolgreich ist. Ein bisschen wie die für Symbian verfügbaren Speichertests.
quelle
Ich sehe, dass Andry Lowry Roy Osheroves Einheitentestmetriken bereits veröffentlicht hat. aber es scheint, dass niemand das (kostenlose) Set vorgestellt hat, das Onkel Bob in Clean Code (132-133) gibt. Er benutzt das Akronym FIRST (hier mit meinen Zusammenfassungen):
quelle