Wir haben den Punkt in unserem Projekt erreicht, an dem wir fast tausend Tests haben und die Leute haben aufgehört, sie auszuführen, bevor sie einchecken, weil es so lange dauert. Bestenfalls führen sie die Tests durch, die für den Code relevant sind, den sie geändert haben, und im schlimmsten Fall checken sie ihn einfach ein, ohne zu testen.
Ich glaube, dass dieses Problem auf die Tatsache zurückzuführen ist, dass die Lösung auf 120 Projekte angewachsen ist (wir machen normalerweise viel kleinere Projekte und dies ist nur das zweite Mal, dass wir TDD richtig durchführen) und die Build + -Testzeit auf ungefähr zwei bis drei Minuten angewachsen ist auf den kleineren Maschinen.
Wie verkürzen wir die Laufzeit der Tests? Gibt es Techniken? Mehr vortäuschen? Weniger vortäuschen? Vielleicht sollten die größeren Integrationstests nicht automatisch ausgeführt werden, wenn alle Tests ausgeführt werden?
Bearbeiten: Als Antwort auf einige der Antworten verwenden wir bereits CI und einen Build-Server. Daher weiß ich, dass die Tests fehlschlagen. Das Problem (eigentlich ein Symptom) ist, dass wir ständig Nachrichten über fehlgeschlagene Builds erhalten. Teilprüfungen durchzuführen, ist etwas, was die meisten Leute tun, aber nicht alle. und in Bezug auf die Tests sind sie eigentlich ziemlich gut gemacht, sie verwenden Fälschungen für alles und es gibt überhaupt keine IO.
quelle
Antworten:
Eine mögliche Lösung wäre, den Testabschnitt von den Entwicklungsmaschinen auf ein kontinuierliches Integrationssetup ( z. B. Jenkins ) zu verschieben, indem Versionskontrollsoftware einer bestimmten Art ( git , svn usw.) verwendet wird.
Wenn neuer Code geschrieben werden muss, erstellt der jeweilige Entwickler eine Verzweigung für alle Aktivitäten im Repository. Alle Arbeiten werden in diesem Zweig ausgeführt und sie können ihre Änderungen jederzeit in den Zweig übertragen, ohne die Hauptcodezeile zu verfälschen.
Wenn die gegebene Funktion, die Fehlerbehebung oder was auch immer sie gerade bearbeiten, abgeschlossen ist, kann dieser Zweig wieder in den Trunk eingefügt werden (oder wie auch immer Sie es vorziehen), in dem alle Komponententests ausgeführt werden. Wenn ein Test fehlschlägt, wird die Zusammenführung abgelehnt und der Entwickler benachrichtigt, damit er die Fehler beheben kann.
Sie können Ihren CI-Server auch die Komponententests für jeden Feature-Zweig ausführen lassen, wenn Commits durchgeführt werden. Auf diese Weise kann der Entwickler einige Änderungen vornehmen, den Code festschreiben und den Server die Tests im Hintergrund ausführen lassen, während er weitere Änderungen oder andere Projekte bearbeitet.
Eine gute Anleitung für eine Möglichkeit, ein solches Setup durchzuführen, finden Sie hier (git-spezifisch, sollte aber für andere Versionskontrollsysteme funktionieren): http://nvie.com/posts/a-successful-git-branching-model/
quelle
Die meisten Unit-Tests sollten jeweils weniger als 10 Millisekunden dauern. Fast tausend Tests zu haben, ist nichts und sollte vielleicht ein paar Sekunden dauern .
Wenn dies nicht der Fall ist, sollten Sie aufhören, hochgradig gekoppelte Integrationstests zu schreiben (es sei denn, der Code benötigt dies) und gute Komponententests schreiben (beginnend mit gut entkoppeltem Code und der richtigen Verwendung von Fakes / Mocks / Stubs / usw.). Diese Kopplung wirkt sich auf die Testqualität und die Zeit aus, die erforderlich ist, um sie zu schreiben - es geht also nicht nur darum, die Testlaufzeit zu verkürzen.
quelle
py.test
) , das jede Menge Magie im Hintergrund ausführt, und alles reinem Python-Code ("100x langsamer als C ") dauert die Ausführung der ca. 500 Tests in einem meiner Projekte auf einem mehrere Jahre alten, langsamen Netbook weniger als 6 Sekunden. Diese Zahl ist in der Anzahl der Tests ungefähr linear; Während ein gewisser Startaufwand anfällt, wird dieser über alle Tests amortisiert, und der Aufwand pro Test beträgt O (1).Es gibt verschiedene Ansätze, mit denen ich ähnliche Probleme gelöst habe:
Darüber hinaus können Sie die folgenden Tools verwenden, um sowohl Ihr Leben zu vereinfachen als auch um Tests zu beschleunigen
pnunit
und CI-Konfiguration mit mehreren Knoten.quelle
0. Hören Sie auf Ihre Programmierer.
Wenn sie die Tests nicht ausführen, bedeutet dies, dass sie die Kosten (Warten auf die Ausführung der Tests, Behandlung falscher Fehler) als höher als den Wert (sofortiges Erkennen von Fehlern) einschätzen. Reduzieren Sie die Kosten, erhöhen Sie den Wert und die Mitarbeiter führen die Tests die ganze Zeit durch.
1. Machen Sie Ihre Tests 100% zuverlässig.
Wenn Sie jemals Tests haben, die mit falschen Negativen scheitern, sollten Sie sich sofort darum kümmern. Reparieren Sie sie, ändern Sie sie, beseitigen Sie sie, was auch immer nötig ist, um 100% ige Zuverlässigkeit zu gewährleisten. (Es ist in Ordnung, eine Reihe von unzuverlässigen, aber dennoch nützlichen Tests zu haben, die Sie separat ausführen können. Der Hauptteil der Tests muss jedoch zuverlässig sein.)
2. Ändern Sie Ihre Systeme, um sicherzustellen, dass alle Tests die ganze Zeit bestehen.
Verwenden Sie kontinuierliche Integrationssysteme, um sicherzustellen, dass nur vorübergehende Commits in der Haupt- / Beamten- / Veröffentlichungs- / beliebigen Zweigstelle zusammengefasst werden.
3. Ändern Sie Ihre Kultur so, dass 100% der Tests bestanden werden.
Unterrichten Sie die Lektion, dass eine Aufgabe erst "erledigt" ist, nachdem 100% der Tests bestanden wurden und sie in den Zweig main / official / release / whatever integriert wurde.
4. Machen Sie die Tests schnell.
Ich habe an Projekten gearbeitet, bei denen Tests eine Sekunde dauern, und an Projekten, bei denen sie den ganzen Tag dauern. Es besteht eine starke Korrelation zwischen der Zeit, die für die Durchführung von Tests benötigt wird, und meiner Produktivität.
Je länger die Tests dauern, desto seltener werden sie ausgeführt. Das bedeutet, dass Sie länger brauchen, ohne Feedback zu den vorgenommenen Änderungen zu erhalten. Dies bedeutet auch, dass Sie zwischen den Commits länger brauchen. Häufigeres Festschreiben bedeutet kleinere Schritte, die einfacher zusammenzuführen sind. Commit-Historie ist leichter zu verfolgen; Es ist einfacher, einen Fehler in der Historie zu finden. Auch das Zurückrollen ist einfacher.
Stellen Sie sich Tests vor, die so schnell ablaufen, dass es Ihnen nichts ausmacht, sie bei jeder Kompilierung automatisch auszuführen.
Schnelle Tests können schwierig sein (das hat das OP gefragt, richtig!). Entkopplung ist der Schlüssel. Mocks / Fakes sind in Ordnung, aber ich denke, Sie können es besser machen, indem Sie überarbeiten, um Mocks / Fakes überflüssig zu machen. Siehe Arlo Belshees Blog, beginnend mit http://arlobelshee.com/post/the-no-mocks-book .
5. Machen Sie Tests nützlich.
Wenn die Tests nicht scheitern, wenn Sie es vermasseln, was ist dann der Sinn? Bringen Sie sich bei, Tests zu schreiben, die die Fehler auffangen, die Sie wahrscheinlich verursachen. Dies ist eine Fähigkeit für sich und wird viel Aufmerksamkeit erfordern.
quelle
Ein paar Minuten ist OK für Unit-Tests. Beachten Sie jedoch, dass es drei Haupttypen von Tests gibt:
Diese sind in der Reihenfolge der Geschwindigkeit aufgelistet. Unit-Tests sollten schnell gehen. Sie werden nicht jeden Fehler erkennen, aber sie stellen fest, dass das Programm vernünftig ist. Unit-Tests sollten in maximal 3 Minuten oder mit angemessener Hardware durchgeführt werden. Sie sagen, Sie haben nur 1000 Unit-Tests, und sie dauern 2-3 Minuten? Nun, das ist wahrscheinlich in Ordnung.
Dinge zu überprüfen:
Stellen Sie jedoch sicher, dass Ihre Komponententests und Integrationstests getrennt sind. Integrationstests sind immer langsamer.
Stellen Sie sicher, dass Ihre Komponententests parallel ausgeführt werden. Es gibt keinen Grund, dies nicht zu tun, wenn es sich um echte Komponententests handelt
Stellen Sie sicher, dass Ihre Komponententests "frei von Abhängigkeiten" sind. Sie sollten niemals auf eine Datenbank oder das Dateisystem zugreifen
Davon abgesehen klingen Ihre Tests im Moment nicht schlecht. Als Referenz hat jedoch einer meiner Freunde in einem Microsoft-Team 4.000 Komponententests, die auf anständiger Hardware in weniger als 2 Minuten ausgeführt werden (und es ist ein kompliziertes Projekt). Schnelle Unit-Tests sind möglich. Das Eliminieren von Abhängigkeiten (und Verspotten nur so oft wie nötig) ist die Hauptsache, um Geschwindigkeit zu erreichen.
quelle
Trainieren Sie Ihre Entwickler in PSP (Personal Software Process), damit sie ihre Leistung durch mehr Disziplin verstehen und verbessern können. Das Schreiben von Code hat nichts damit zu tun, dass Sie mit den Fingern auf eine Tastatur schlagen und anschließend einen Compile- und Check-in-Button drücken.
PSP war in der Vergangenheit sehr beliebt, als das Kompilieren von Code viel Zeit in Anspruch nahm (Stunden / Tage auf einem Mainframe, sodass jeder den Compiler mitbenutzen musste). Aber als persönliche Workstations leistungsfähiger wurden, akzeptierten wir alle den Prozess:
Wenn Sie überlegen, bevor Sie tippen, und dann nach dem Tippen überprüfen, was Sie geschrieben haben, können Sie die Anzahl der Fehler reduzieren, bevor Sie eine Build- und Testsuite ausführen. Lernen Sie, Build nicht 50-mal am Tag zu drucken, sondern ein- oder zweimal. Dann ist es weniger wichtig, dass Ihre Build- und Testzeit einige Minuten länger dauert.
quelle
Ein möglicher Weg: Teilen Sie Ihre Lösung. Wenn eine Lösung 100 Projekte umfasst, ist sie nicht mehr zu handhaben. Nur weil zwei Projekte (z. B. A und B) einen gemeinsamen Code aus einem anderen Projekt (z. B. Lib) verwenden, müssen sie sich nicht in derselben Lösung befinden.
Stattdessen können Sie Lösung A mit Projekten A und Lib sowie Lösung B mit Projekten B und Lib erstellen.
quelle
Ich bin in einer ähnlichen Situation. Ich habe Unit-Tests, die die Kommunikation mit dem Server testen. Sie testen das Verhalten mit Zeitüberschreitungen, brechen Verbindungen usw. ab. Die gesamte Testreihe dauert 7 Minuten.
7 Minuten sind eine relativ kurze Zeit, aber nicht vor jedem Commit.
Wir haben auch eine Reihe von automatisierten UI-Tests, deren Laufzeit 2 Stunden beträgt. Es ist nicht etwas, das Sie jeden Tag auf Ihrem Computer ausführen möchten.
Also, was ist zu tun?
Das Wichtigste ist: Alle Ihre Tests sollten häufig ausgeführt werden, da es wichtig ist, die Fehler zu finden. Es ist jedoch nicht unbedingt erforderlich, sie vor dem Festschreiben zu finden.
quelle
Obwohl Ihre Beschreibung des Problems keinen gründlichen Einblick in die Codebasis gibt, kann ich mit Sicherheit sagen, dass es sich um ein zweifaches Problem handelt.
Lerne die richtigen Tests zu schreiben.
Sie sagen, Sie haben fast tausend Tests und Sie haben 120 Projekte. Angenommen, höchstens die Hälfte dieser Projekte sind Testprojekte, haben Sie 1000 Tests für 60 Produktionscode-Projekte. Das gibt Ihnen etwa 16-17 Tests pro. Projekt!!!
Das ist wahrscheinlich die Menge an Tests, die ich in einem Produktionssystem für 1-2 Klassen durchführen müsste. Wenn Sie also nicht nur 1-2 Klassen in jedem Projekt haben (in diesem Fall ist Ihre Projektstruktur zu feinkörnig), sind Ihre Tests zu groß, sie decken zu viel Boden ab. Sie sagen, dies ist das erste Projekt, bei dem Sie TDD ordnungsgemäß durchführen. Angenommen, die von Ihnen angegebenen Zahlen weisen darauf hin, dass dies nicht der Fall ist und Sie keine TDD-Eigenschaft ausführen.
Sie müssen lernen, die richtigen Tests zu schreiben. Dies bedeutet wahrscheinlich, dass Sie zunächst lernen müssen, wie Sie den Code testbar machen. Wenn Sie innerhalb des Teams keine Erfahrung dafür finden, würde ich vorschlagen, Hilfe von außen anzustellen, z. B. in Form von einem oder zwei Beratern, die Ihrem Team über einen Zeitraum von zwei bis drei Monaten dabei helfen, testbaren Code zu schreiben minimale Unit-Tests.
Zum Vergleich: In dem .NET-Projekt, an dem ich gerade arbeite, können wir ungefähr 500 Unit-Tests in weniger als 10 Sekunden durchführen (und das wurde nicht einmal auf einem High-Spec-Computer gemessen). Wenn das Ihre Zahlen wären, hätten Sie keine Angst davor, diese von Zeit zu Zeit vor Ort zu betreiben.
Erfahren Sie, wie Sie die Projektstruktur verwalten.
Sie haben die Lösung in 120 Projekte unterteilt. Das ist nach meinen Maßstäben eine erstaunliche Anzahl von Projekten.
Wenn es also Sinn macht, tatsächlich so viele Projekte zu haben (was meines Erachtens nicht der Fall ist - aber Ihre Frage enthält nicht genügend Informationen, um dies beurteilen zu können), müssen Sie die Projekte in kleinere Komponenten aufteilen, die kann separat erstellt, versioniert und bereitgestellt werden. Wenn ein Entwickler die Testsuite auf unit ausführt, muss er nur die Tests ausführen, die sich auf die Komponente beziehen, an der er gerade arbeitet. Der Build-Server sollte sicherstellen, dass alles korrekt integriert ist.
Die Aufteilung eines Projekts in mehrere Komponenten, die separat erstellt, versioniert und bereitgestellt werden, erfordert meiner Erfahrung nach ein sehr ausgereiftes Entwicklungsteam, ein Team, das ausgereifter ist, als ich das Gefühl habe, dass Ihr Team es ist.
In jedem Fall müssen Sie jedoch etwas an der Projektstruktur ändern. Teilen Sie die Projekte entweder in separate Komponenten auf oder beginnen Sie mit dem Zusammenführen von Projekten.
Fragen Sie sich, ob Sie wirklich 120 Projekte benötigen?
ps Vielleicht möchten Sie NCrunch ausprobieren. Es ist ein Visual Studio-Plug-In, das Ihren Test automatisch im Hintergrund ausführt.
quelle
JUnit-Tests sind normalerweise schnell durchzuführen, aber einige von ihnen müssen nur einige Zeit in Anspruch nehmen, um sie auszuführen.
Beispielsweise dauert der Datenbanktest in der Regel einige Zeit, bis er initialisiert und abgeschlossen ist.
Wenn Sie Hunderte von Tests haben, selbst wenn sie schnell sind, benötigen sie aufgrund ihrer Anzahl viel Zeit, um ausgeführt zu werden.
Was getan werden kann, ist:
1) Identifizieren Sie die entscheidenden Tests. Die für die wichtigsten Teile von Bibliotheken und die, die nach Änderungen am wahrscheinlichsten versagen. Nur dieser Test sollte immer beim Kompilieren ausgeführt werden. Wenn ein Code häufig beschädigt ist, sollten seine Tests obligatorisch sein, auch wenn die Ausführung lange dauert. Wenn andererseits ein Teil der Software nie ein Problem verursacht hat, können Sie Tests für jeden Build sicher überspringen.
2) Bereiten Sie den Continuous Integration Server vor, auf dem alle Tests im Hintergrund ausgeführt werden. Es liegt an Ihnen, ob Sie sich entscheiden, stündlich oder nach jedem Commit zu bauen (der zweite Schritt ist nur sinnvoll, wenn Sie automatisch erkennen möchten, wessen Commit Probleme verursacht hat).
quelle
Probleme, die ich gesehen habe:
a) Verwenden von IOC zum Aufbau von Testelementen. 70 Sekunden -> 7 Sekunden durch Entfernen des Behälters.
b) Nicht alle Klassen verspotten. Halten Sie Ihre Unit-Tests auf ein einzelnes Element. Ich habe Tests gesehen, die durch ein paar Klassen streifen. Dies sind keine Komponententests und es ist wahrscheinlicher, dass sie brechen.
c) Profilieren Sie sie, um herauszufinden, was passiert ist. Ich fand, dass der Konstruktor Dinge baute, die ich nicht brauchte, also lokalisierte ich sie und reduzierte die Laufzeit.
d) Profil. Vielleicht ist der Code nicht so gut und Sie können durch eine Überprüfung etwas Effizienz gewinnen.
e) Entfernen Sie Abhängigkeiten. Wenn Sie die ausführbare Datei klein halten, wird die Ladezeit verkürzt. Verwenden Sie eine Schnittstellenbibliothek und IOC-Container, um Ihre endgültige Lösung auszuführen. In Ihren Haupttestprojekten sollte jedoch nur die Schnittstellenbibliothek definiert sein. Dies stellt die Trennung sicher, erleichtert das Testen und verkleinert den Testfußabdruck.
quelle
Ich fühle deinen Schmerz und bin an verschiedenen Stellen gelaufen, an denen die Build-Geschwindigkeit erheblich verbessert werden kann. Ich empfehle jedoch, die Anzahl an Details zu messen, um herauszufinden, wo Ihr Build am längsten dauert. Zum Beispiel habe ich einen Build mit ungefähr 30 Projekten, dessen Ausführung etwas mehr als eine Minute dauert. Dies ist jedoch nur ein Teil des Bildes. Ich weiß auch, welche Projekte am längsten dauern, was mir hilft, meine Bemühungen zu konzentrieren.
Dinge, die die Bauzeit verschlingen:
Mock-Bibliotheken verwenden entweder Reflection oder injizieren Code mithilfe von Bytecode-Bibliotheken, um das Mock für Sie zu generieren. Es ist zwar sehr praktisch, nimmt aber die Testzeit in Anspruch. Wenn Sie in Ihrem Test in einer Schleife Verspottungen generieren, kann dies den Komponententests eine messbare Zeitspanne hinzufügen.
Es gibt verschiedene Möglichkeiten, um die Probleme zu beheben:
Wenn Ihre Lösung über 100 Projekte enthält, verfügen Sie über eine Kombination aus Bibliothekscode, Tests und Anwendungscode. Jede der Bibliotheken kann eine eigene Lösung mit den zugehörigen Tests sein. Jet Brains Team City ist ein CI-Build-Server, der auch als Nuget-Server fungiert - und ich bin sicher, dass es nicht der einzige ist. Dies gibt Ihnen die Flexibilität, Bibliotheken, die wahrscheinlich nicht oft geändert werden, in ihre eigenen Lösungen / Projekte zu verschieben und mithilfe von Nuget die Abhängigkeiten für Ihren Anwendungscode aufzulösen. Kleinere Lösungen bedeuten, dass Sie Ihre Änderungen an einer Bibliothek schnell und unkompliziert vornehmen und die Vorteile der Hauptlösung nutzen können.
quelle
Kann Ihre Testumgebung überall ausgeführt werden? Verwenden Sie, falls dies möglich ist, Cloud Computing, um die Tests auszuführen. Teilen Sie die Tests auf N virtuelle Maschinen auf. Wenn die Zeit für die Ausführung der Tests auf einem einzelnen Computer T1 Sekunden beträgt, kann sich die Zeit für die Aufteilung T2 T2 = T1 / N nähern. (Angenommen, jeder Testfall benötigt ungefähr die gleiche Zeit.) Und Sie müssen nur für die VMs bezahlen, wenn Sie sie verwenden. Sie haben also nicht rund um die Uhr einen Haufen Testmaschinen in einem Labor. (Ich würde dies gerne dort tun, wo ich arbeite, aber wir sind an bestimmte Hardware gebunden. Keine VMs für mich.)
quelle