2008-11-28 18 views
7

Ich habe ein wenig über Komponententests gelesen und habe mich gefragt, wie Sie Unit-Test testen. Anscheinend soll ein Unit-Test ein Programm in sehr kleine "Einheiten" zerlegen und die Funktionalität von dort aus testen.Wie testen Sie Einheit?

Aber ich frage mich, ist es genug, Unit-Test zu testen? Oder nehmen Sie es noch weiter und testen Algorithmen, Formeln, etc.? Oder erweitern Sie es auf Unit-Test asp Seiten/Funktionalität? Oder machen Sie Unit-Test überhaupt?

Antwort

4

Aber ich frage mich, ist es genug, Unit-Test eine Klasse zu testen? Oder nehmen Sie es noch weiter und testen Algorithmen, Formeln, etc.? Oder erweitern Sie es auf Unit-Test asp Seiten/Funktionalität? Oder machen Sie Unit-Test überhaupt?

Ein Algorithmus sollte in einer Klasse sein und automatisch Unit Getestet sein.Eine Formel ist innerhalb der Klasse als Funktion und sie sind Einheit getestet auch. Unit Testing testet Verhalten, Zustand und alle Dinge, die für die kleinste Entwicklungseinheit getestet werden können. Also ja, der Algorithmus wird mit allen Details getestet. Später, wenn Sie Klassen haben, die die andere Klasse verwenden, werden Sie Integration Tests durchführen (diese werden oft mit Unit Test-Programmen getestet). Dies wird das gleiche, aber auf einer höheren Ebene sein.

2

i Komponententest Funktionen, nicht einzelne Methoden oder Klassen. Der Aufwand für das Schreiben und Warten von Komponententests ist nicht unerheblich, und im Allgemeinen empfehle ich nicht, Komponententests für jedes Bit zu schreiben. Unit-Testing-Funktionen sind jedoch lohnenswert, denn Funktionen sind das, wofür der Client Sie bezahlt.

1

Wir programmieren normalerweise Java-Bibliotheken für Maschinen. Ein Programm wird normalerweise von mehr als zwanzig Bibliotheken gebildet, was wir tun, ist Unit-Test jeder Bibliothek. Es ist keine einfache Aufgabe, da Bibliotheken oft sehr eng miteinander verbunden sind und dies nicht oft möglich ist.

Unser Code ist nicht so modular wie wir es gerne hätten, aber wir müssen mit ihm leben, um Kompatibilitätsprobleme zu vermeiden, und die Verbindungsunterbrechung bedeutet auch in vielen Fällen die Kompatibilität.

1

Ich teste so viel von der öffentlichen Schnittstelle wie ich kann (ich benutze C++, aber die Sprache ist nicht wirklich wichtig). Der wichtigste Aspekt ist das Schreiben von Tests beim Schreiben des Codes (unmittelbar davor oder danach). Aus Erfahrung versichere ich Ihnen, dass die Entwicklung auf diese Weise zu einem zuverlässigeren Code führt. und wird es einfacher zu pflegen machen (wie Änderungen, die Tests brechen werden offensichtlich sofort sein). Für alle Projekte empfehle ich, Tests von Anfang an zu berücksichtigen - wenn Sie eine Klasse schreiben, die von einer anderen komplizierten Klasse abhängt, dann verwenden Sie eine Schnittstelle, damit Sie die komplizierteren Objekte beim Testen "überspielen" können (Datenbankzugriff) , Netzwerkzugriff usw.).

Wenn Sie viele Tests schreiben, werden Sie zwar langsamer, aber in der Realität verbringen Sie während der Projektlaufzeit weniger Zeit mit der Behebung von Fehlern.

Testen Sie oft - wenn es kaputt gehen kann, wird es - und es bricht besser, wenn Sie es testen, als wenn ein Kunde versucht, es zu benutzen.

2

Dies sind allgemeine Richtlinien, die ich nützlich für Unit-Tests finden:

1) Identifizieren Boundary Objects (Win/WebForms, Custom usw.).

2) Identifizieren Steuerungsobjekte (Business Layer-Objekte)

3) Stellen Sie sicher, Einheit schreiben Tests mindestens zur Steuerung durch Grenzobjekte aufgerufen öffentliche Methoden-Objekte.

Auf diese Weise werden Sie sicher sein, dass Sie die wichtigsten funktionalen Aspekte (Funktionen) Ihrer App abdecken und nicht das Risiko von Mikrotests eingehen (außer Sie möchten).

4

Ich verwende Komponententests als Werkzeug, um zu messen, ob etwas noch funktioniert oder nicht, nachdem ich einige Änderungen am Code vorgenommen habe (z. B. Refactoring, Beheben eines Fehlers, Hinzufügen einer Erweiterung). Da ich Java verwende, werden Komponententests mit JUnit weitgehend automatisiert. Ich rufe nur ein Befehlszeilenskript auf und es führt hunderte von Tests durch, um zu verifizieren, dass der Code nicht kaputt ist.

1

Es reicht nicht aus, nur eine Klasse zu testen. Klassen arbeiten zusammen, und das muss auch getestet werden.

Es gibt mehr Einheiten als nur Klassen:

  • Module,
  • Schichten,
  • Frameworks.

Und es gibt natürlich verschiedene Formen des Testens, z.B. Integration und Akzeptanz.

Ich teste die Dinge, die ich schwierig finde, die Dinge, die ich denke, könnte sich ändern, Schnittstellen und die Dinge, die ich beheben musste. Und meistens beginne ich mit dem Test und versuche sicherzustellen, dass ich das Problem verstehe, das ich lösen möchte.

2

Ich bin ein ziemlich schlampiger Komponententester, aber dann bin ich ein Akademiker, also sind die meisten meiner Programme Skripte für mich selbst oder mehr schwere Programme für meine Forschung. Viele meiner Arbeiten beschäftigen sich mit Compilern, daher ist das Testen klassischer Einheiten schwierig - zum Beispiel ist es nicht so einfach, einen Registerzuordner zu testen, wenn Sie nicht von einem Compiler umgangen werden, und an diesem Punkt können Sie auch einfach weitergehen Regressionstests.

Aber es gibt einige große Ausnahmen. Ich mache ein riesiges Scripting in Lua, das in Module unterteilt ist (eine Quelldatei kann und ist oft ein Modul). Wenn ich an neuen Sachen arbeite, wie zum Beispiel Hilfsprogramme für die Interaktion mit der Shell, werde ich einfach einige Komponententests in das Modul selbst fallen lassen. wo sie jedes Mal ausgeführt werden, wenn das Modul geladen wird. Lua ist so schnell, dass das normalerweise keine Rolle spielt. Hier sind einige Beispiele:

 
assert(os.quote [[three]] == [[three]]) 
assert(os.quote [[three"]] == [['three"']]) 
assert(os.quote [[your mama]] == [['your mama']]) 
assert(os.quote [[$i]] == [['$i']]) 

Wenn ich ein guter Hund bin, schreibe ich ein paar einfache Tests wie diese, bevor ich die Funktion schreibe.

Die andere Sache, die ich mit Unit-Tests zu tun, ist, dass, wenn es etwas hart, ich Test algebraische GesetzeQuickCheck verwenden, das ein statistisches Testwerkzeug ist, die geglaubt wird gesehen werden muss. Es ist das einzige Werkzeug, das ich jemals verwendet habe, das Unit-Test macht Spaß. Ein Link dort ist baumelnd, aber Sie können Tom Moertel's story about the ICFP programming contest auf seinem Blog finden.

Ich hoffe, Sie finden das hilfreich. QuickCheck hat meinen Speck viele Male gespeichert. Kürzlich habe ich den Code für die diskrete Kosinustransformation mit exakter rationaler Arithmetik getestet --- und dann nach C!

1

Nur weil es kompiliert bedeutet nicht, dass es läuft! Das ist die Essenz von Komponententests. Probieren Sie den Code aus.Stellen Sie sicher, dass es tut, was Sie dachten.

Lässt es sich, wenn Sie eine Matrix-Transformation von Matlab bringen, ist es leicht, ein Plus-oder Minuszeichen irgendwo zu vermasseln. So etwas ist schwer zu sehen. Ohne es auszuprobieren, wissen Sie einfach nicht, ob es richtig funktioniert. Das Debuggen von 100 Codezeilen ist viel einfacher als das Debuggen von 100.000 Codezeilen.


Einige Leute nehmen dies zu Extremen. Sie versuchen alles mögliche zu testen. Testen wird zum Selbstzweck.

Dies kann später während der Wartungsphasen nützlich sein. Sie können schnell überprüfen, ob Ihre Updates nichts beschädigt haben.

Aber der Overhead kann die Produktentwicklung behindern! Und zukünftige Änderungen, die die Funktionalität ändern, können einen umfangreichen Test-Update-Overhead erforderlich machen.


Letztes Ende (Es kann auch in Bezug auf Multi-Threading und willkürliche Ausführungsreihenfolge. Chaotisch), sofern nichts anderes angegeben, meine Tests versuchen, den Mittelweg zu schlagen.

Ich versuche, größere Granularitäten zu testen, um grundlegende grundlegende Funktionen zu überprüfen. Ich sorge mich nicht so sehr um jedes mögliche Szenario eines Zaunpfostens. (Das ist, was ASSERT-Makros sind.)

Zum Beispiel: Als ich Code zum Senden/Empfangen von Nachrichten über UDP schrieb, warf ich einen schnellen Test zum Senden/Empfangen von Daten mit dieser Klasse über die Loopback-Schnittstelle. Nichts Außergewöhnliches. Schnell, schnell, & schmutziger Code. Ich wollte es einfach ausprobieren. Um sicherzustellen, dass es tatsächlich funktionierte, bevor ich etwas aufbaute.

Ein anderes Beispiel: Einlesen von Kamerabildern von einer Firewirekamera. Ich warf eine schnelle & dreckige GTK-App zusammen, um die Bilder zu lesen, zu verarbeiten und in Echtzeit anzuzeigen. Andere Leute nennen das Integrationstests. Aber ich kann damit meine Firewire-Schnittstelle, meine Image-Klasse, meine Bayer RGGB-> RGB-Transformation, meine Bildausrichtung & Ausrichtung überprüfen, auch wenn die Kamera wieder kopfüber montiert wurde. Detailliertere Tests wären nur dann gerechtfertigt gewesen, wenn sich dies als unzureichend erwiesen hätte.

Auf der anderen Seite, auch für etwas so einfach wie:

template<class TYPE> inline TYPE MIN(const TYPE & x, const TYPE & y) { return x > y ? y : x; } 
template<class TYPE> inline TYPE MAX(const TYPE & x, const TYPE & y) { return x < y ? y : x; } 

ich eine 1 Zeile SHOW Makro, um sicherzustellen, schrieb ich hatte nicht das Zeichen verkorkst:

SHOW(MIN(3,4)); SHOW(MAX(3,4)); 

All Ich wollte überprüfen, ob es im allgemeinen Fall das tut, was es tun soll. Ich sorge mich weniger darum, wie es mit NaN/+ -Infinity/(double, int) umgeht, als ob einer der Kollegen sich dafür entschieden hat, die Reihenfolge der Argumente zu ändern und zu scheitern.


Werkzeug weise, es gibt eine Menge Unit-Test-Sachen da draußen. Wenn es dir hilft, mehr Kraft für dich. Wenn nicht, müssen Sie nicht wirklich zu extravagant werden.

Ich werde oft ein Testprogramm schreiben, die Daten in und aus einer Klasse-Dumps und druckt sie dann alle mit einem SHOW Makro aus:

#define SHOW(X) std::cout << # X " = " << (X) << std::endl 

(Alternativ können viele meiner Klassen Selbst Drucke mit einem eingebauten Operator < < (ostream &) Methode. Es ist eine erstaunlich nützliche Technik für die Fehlersuche sowie zum Testen!)

Makefiles kann trivialerweise automatisch erweitert werden, um die Ausgabedateien von Testprogrammen zu erzeugen, und um automatisch vergleichen (diff) diese Ausgabedateien mit vorher bekannte (überprüfte) Ergebnisse.

Nicht schick, vielleicht etwas weniger als elegant, aber wie Techniken gehen, ist dies sehr effektiv, schnell zu implementieren und sehr geringen Overhead. (Was hat seine Vorteile, wenn Ihr Manager mißbilligt Zeit auf diesem Test Sachen verschwenden.)


Ein letzter Gedanke, den ich Ihnen verlassen werde. Das wird mich abschreiben lassen, also NICHT tun Sie es!

Vor einiger Zeit brauchte ich ein Testprogramm. Es war ein erforderliches Ergebnis. Das Programm selbst musste überprüfen, dass eine andere Klasse ordnungsgemäß funktionierte. Es konnte jedoch nicht auf externe Datendateien zugreifen. (Wir konnten uns nicht darauf verlassen, wo das Programm relativ zu irgendetwas anderem liegen würde. Auch keine absoluten Pfade.) Das Unit-Testing-Framework für das Projekt war nicht kompatibel mit dem Compiler, den ich verwenden musste. Es musste auch in einer Datei sein. Das Makefile-System des Projekts unterstützte das Verknüpfen mehrerer Dateien für ein Testprogramm nicht. (Anwendungsprogramme, sicher. Sie konnten Bibliotheken. Aber nur eine einzige Datei für jedes Testprogramm.)

Also, Gott verzeih mir, ich „brach die Regeln“ ...

<verlegen>
Ich habe Makros verwendet. Wenn ein #define-Makro festgelegt wurde, wurden die Daten in eine zweite .c-Datei als Initialisierer für ein struct-Array geschrieben. Anschließend, als die Software neu kompiliert wurde und die zweite .c-Datei (mit dem struct-Array) # eingeschlossen war und das #define-Makro nicht gesetzt war, wurden die neuen Ergebnisse mit den zuvor gespeicherten Daten verglichen. Ja, ich habe eine .c-Datei eingeschlossen. O die Verlegenheit von allem.
</verlegen >

Aber es kann getan werden ...

Verwandte Themen