So strukturieren Sie Komponententests für eine GUI-App mit C # und NUnit

16

Ich wurde gebeten, ein kleines Nebenprojekt durchzuführen, um einem unserer Kunden eine einfache Anwendung zur Verfügung zu stellen. Normalerweise arbeite ich an Back-End-Code, bei dem alle meine Testanforderungen geklärt sind, und ich hatte noch nicht das zweifelhafte Vergnügen, Tests für die GUI zu schreiben. Daher ist mir ein wenig unklar, wie ich mich einrichten soll den Testcode und die Tools für eine EXE.

Mein erster Instinkt bestand darin, die Tests einfach in den Anwendungscode aufzunehmen, was jedoch die Angabe einer Reihe von testspezifischen Abhängigkeiten erforderlich machte, die ich angewiesen hatte, ausdrücklich nicht an den Kunden zu versenden. Ich bin auch nicht in der Lage, Geld für ein speziell entwickeltes Test-Tool herauszuholen . Daher muss ich die Tools verwenden, die ich zur Hand habe ( StoryQ , RhinoMocks und NUnit)), was eigentlich mehr als genug sein sollte, um das Verhalten einer einfachen GUI-App zu testen. Soweit ich sehen kann, muss ich versuchen, ein ausgewogenes Verhältnis zwischen einer wirklich einfachen Gestaltung und einer gezielten Überentwicklung für die Tests zu finden. Es sieht so aus, als würde ich die App mit der Geschäftslogik in einer separaten Bibliothek erstellen und wie gewohnt mit der Bibliothek testen oder einen anderen Mechanismus finden, der es mir ermöglicht, die ausführbare Datei zu erstellen, ohne zusätzliche Module zu entfernen, die das Anwendungsdesign nicht unterstützt wirklich brauchen.

Bearbeiten:
Bitte beachten Sie, dass es bei dieser Frage darum geht, die Beziehung zwischen NUnit und meiner ausführbaren Datei im Gegensatz zu einer DLL zu strukturieren und nicht darum, wie Präsentation und Geschäftslogik voneinander getrennt werden.
/Bearbeiten

Meine Frage lautet also:

  1. Gibt es eine bestimmte / empfohlene Methode zum Konfigurieren einer einfachen GUI-Anwendung mit Komponententests, mit der ich den Status und das Verhalten mit den verfügbaren Tools angemessen überprüfen kann, ohne zu viel Engineering betreiben zu müssen?
  2. Habe ich etwas Grundsätzliches darüber übersehen, wie NUnit beim Testen einer EXE (im Gegensatz zu einer DLL) aufgerufen / konfiguriert werden sollte?
  3. Können Sie mir Beispiele geben oder zeigen, wie dies alles erreicht werden kann?

Mir ist klar, dass es mehr als einen Weg gibt, dies zu tun. Daher suche ich nach spezifischen Implementierungsrichtlinien, die auf Ihren Erfahrungen basieren.

S.Robins
quelle
NUnit ist nicht dafür ausgelegt, GUIs direkt zu testen. Sie müssen Ihre Präsentationsebene (dh die Ansicht) von Ihren Daten und Ihrer Geschäftslogik (dh Ihrem Modell) trennen, damit Sie testen können, was in Ihre Ansicht einfließt, ohne die Ansicht zu verwenden.
Bernard
1
@Bernard Bei dieser Frage geht es nicht darum, eine GUI zum Testen zu überlagern. Ich überlagere natürlich alle meine Apps - auch die trivialen -, so dass das für mich wirklich kein Problem ist. Ich habe die Frage entsprechend bearbeitet und hoffe, dass sie etwaige Missverständnisse aus dem Weg räumt. :)
S.Robins
1
Es gibt nichts schrecklich Kompliziertes beim Testen von Einheiten in EXEs. Lassen Sie einfach Ihre Test-DLL auf Ihre EXE-Datei verweisen, und Sie können loslegen.
Whatsisname

Antworten:

3

Ich erwähnte in einem meiner Kommentare zu Simoramans Antwort, dass ich mir ein paar Möglichkeiten überlegt hatte, dies zu tun. Eine meiner Optionen ähnelte dem Vorschlag in Jalayns Antwort , ein doppeltes Projekt zu erstellen und eine DLL zu generieren, während meine andere Idee darin bestand, einfach auf die Dateien im Projekt zu verlinken, in denen sich Code befand, den ich testen wollte. Obwohl beide Optionen zum Funktionieren gebracht werden könnten, sind sie nicht ideal.

Im zweiten Fall hätte ich ein Durcheinander von Einheitenabhängigkeiten zu verwalten, es sei denn, ich könnte die Architektur wirklich auseinanderreißen, um Abhängigkeiten zu minimieren. Dies ist in Ordnung für kleinere Projekte, aber größere können leicht zu einem echten Chaos werden. Mein größter Widerstand gegen diese Option ist jedoch die schiere Unaufmerksamkeit. Klar könnte ichDamit es funktioniert, muss ich die Kapselung effektiv aufheben, um die Interna einer Assembly direkt über die Quelle zu testen, anstatt die über die öffentlichen Schnittstellen zu testen, was in meinen Augen ein großes No-No ist. Ebenso würde das Vorhandensein einer zusätzlichen Projektdatei bedeuten, entweder zwei Projekte gleichzeitig zu duplizieren oder eine Möglichkeit zu finden, Projektdateieinstellungen automatisch zwei Dateien gleichzeitig hinzuzufügen, oder daran zu denken, das Projektfeld jedes Mal zu kopieren und umzubenennen, wenn ich es erstelle. Dies kann auf dem Build-Server möglicherweise automatisiert werden, ist jedoch in der IDE nur schwer zu verwalten. Auch hier kann es funktionieren, aber es ist bestenfalls ein Trick und schlimmer, wenn Sie es falsch verstehen.

Der beste Weg scheint zu sein, wie Whatsisname auf meine Frage kommentiert, und einfach die EXE als Referenz in das Testprojekt aufzunehmen. Es stellt sich heraus , dass eine EXE effektiv die gleiche Weise wie eine DLL in diesem Fall behandelt, und ich bin in der Lage , all meine zugreifen schön geschichtet Klassen zu testen , was mein Boot schwimmt.

S.Robins
quelle
2

Ich denke, dass:

  • Ihr Business-Testcode sollte sich in einem separaten Projekt befinden und Ihre Business-Code-Bibliothek testen.
  • Ihr GUI-Testcode sollte sich in einem separaten Projekt befinden und Ihre GUI-Bibliothek testen. Nun, wie man eine GUI-Bibliothek anstelle einer ausführbaren Datei erstellt, versuche ich, dies später zu beantworten.
  • Wenn Sie eine my.namespace.biz.MyClass haben, sollte Ihre Testklasse my.namespace.biz.MyClassTest (oder MyClassTestCase) sein.
  • Wenn Sie den in Ihrem ausführbaren Ziel gefundenen Code testen möchten, sollten Sie ein Setup haben, das eine EXE-Datei erstellt, und ein anderes Setup, das eine Bibliothek (DLL) erstellt, mit der Sie Ihre Tests starten.

Dies sind die Regeln, denen ich gerne folge, egal ob es sich um Java oder C # handelt (außer es gibt natürlich kein EXE-Problem mit Java :-))

Was die Konfiguration Ihrer Testumgebung angeht, haben Sie meines Erachtens mindestens die folgenden zwei Möglichkeiten:

Mit MSBuild

Erstellen Sie einen Klon Ihrer .proj-Datei (sagen Sie myproject-as-dll.proj ). Ändern Sie die OutputTypein der geklonten Datei von " EXE" in " Library". Mit dem Befehl MSBuild können Sie jetzt eine Bibliothek erstellen, die Sie als Referenz für Ihr Projekt mit NUnit-Testfällen festlegen können.

Es scheint mir möglich zu sein, aber ich habe es noch nie so ehrlich benutzt, also bin ich mir nicht sicher. Außerdem ist MSBuild möglicherweise nicht auf Ihrem Integrationstestserver vorhanden, und ich weiß nicht, ob es von Visual Studio getrennt werden kann.

Mit NAnt

Wenn Sie mit NAnt nicht vertraut sind, müssen Sie sich überlegen, wie Sie Ihre Projektbuilds damit konfigurieren können. Vielleicht sehen Sie sich das an , es ist ein bisschen alt, aber der Autor hat die NAnt-Dateien kommentiert und wenn es selbsterklärend ist ( Bearbeiten: seine Datei genauer untersuchen, finde ich seine Konfigurationsdatei extrem wiederverwendbar ). Er kann auch viel mehr als nur erstellen, da er Testfälle ausführt und Tools zur Codeabdeckung startet. Nun, ich gebe zu, ich habe NAnt nie benutzt, im Gegensatz zu seinem Java-Gegenstück und Vater "Ant", das ich oft benutzt habe, aber ich sehe, dass es ziemlich dasselbe ist und ich denke nicht, dass es so schwer zu lernen ist.

Mit diesem Tool können Sie eine Konfiguration erstellen, mit der Sie:

  • Erstellen Sie alle Ihre Projekte (Geschäftslogik, GUI usw.) in separaten Bibliotheken
  • Erstellen Sie Ihre Testprojekte
  • Starten Sie die Tests (dieser spezielle Teil wird mit der NUnit2-Task ausgeführt ).
  • Überprüfen Sie Ihre Code-Abdeckung mit der NCover-Aufgabe .

Mit etwas mehr Code könnten Sie sogar:

  • Führen Sie nächtliche Bereitstellungen auf Ihrem Integrationsserver durch
  • Wenn NAnt auf Ihrem Integrationsserver verfügbar ist, starten Sie nächtliche Integrationstests mithilfe von geplanten Tasks

Alles wird ohne Änderungen in Ihren Visual Studio-Dateien durchgeführt. Eigentlich scheint es mir nicht übertrieben zu sein, es ist nur eine Datei. Es könnte einen, vielleicht zwei Tage dauern, bis alles funktioniert, aber Sie werden meiner Meinung nach ein gutes Setup haben.

Zuletzt würde ich dem Kunden alles geben, was notwendig ist, um die Projekte zu erstellen, zu testen und auszuführen. Ich neige dazu zu denken, dass es Ihre Professionalität und die Tatsache zeigt, dass Sie Code mit Qualität in Ihrem Kopf schreiben (was Sie meiner Meinung nach tun, weil Sie nach eleganten Lösungen suchen).

Jalayn
quelle
0

Nur weil das Projekt (anfangs) klein ist, heißt das noch lange nicht, dass die richtige Architektur zu hoch ist. Die Tatsache, dass Sie Tests schreiben möchten, zeigt, dass Ihr Projekt kein ganz trivialer einmaliger Hack ist.

Sie haben nicht erwähnt, welches GUI-Framework Sie verwenden. WPF MVVM (Model-View-ViewModel) ist gut und ermöglicht es Ihnen, ganz einfach Tests für die gesamte Logik zu schreiben. Mit WinForms habe ich gute Dinge über MVP (Model-View-Presenter) gehört

Simoraman
quelle
Ich schreibe Tests für den gesamten Code, den ich schreibe. Sogar das Zeug, das du vielleicht trivial findest. Das einzige Mal, dass ich keinen Test schreibe, ist, wenn ich spitze. In diesem Fall versende ich ein einmaliges Dienstprogramm an einen Kunden. Das Testen ist also mehr als nur ein Luxus. Es ist eine Anforderung, um unsere Qualitätsstandards zu erfüllen. In Bezug auf "Over Engineering" ist dies keine Wahl zwischen guter oder schlechter Architektur, sondern vermeidet die Notwendigkeit, zusätzliche Schichten zu erstellen, die in diesem Fall nicht erforderlich sind, da die App nur einen Zweck mit einem relativ kurzen Lebenszyklus hat.
S.Robins
In Bezug auf die Wahl des GUI-Frameworks sehe ich keine Auswirkungen auf die Art und Weise, in der die Testumgebung eingerichtet wird. Ich bin auf der Suche nach dem WIE, um Unit-Tests für die GUI-Ebene mithilfe der verfügbaren Tools zu implementieren. Diese spezielle Antwort sagt mir nichts darüber.
S.Robins
Simoraman - Wenn Sie den ziemlich wertenden ersten Absatz wegnehmen würden, würde dies zu einer Antwort führen. Repariere das und ich entferne meine -1. @ S.Robins beachten Sie, dass der zweite Absatz ist relevant - wenn auch nicht eine vollständige Antwort, es würde helfen. Wenn Ihre GUI-Schicht dünn, gut strukturiert und offensichtlich ist und die gesamte Geschäftslogik durch Komponententests auf Modellebene getestet wird, müssen Sie möglicherweise nicht die zusätzliche Mühe auf sich nehmen, die Benutzeroberfläche explizit zu testen.
Mark Booth
1
@ MarkBooth Layering ist eigentlich kein Problem. Wie Simiraman erwähnt, kann ich MVP, MVVM oder etwas noch Dünneres bauen. Ich habe jedoch einige GUI-spezifische Elemente, die explizit getestet werden müssen, weshalb ich mich entschlossen habe, dies als Frage zu formulieren. Ich habe ein paar Ideen, und im schlimmsten Fall weiß ich, dass ich das Problem irgendwann selbst lösen und eine Antwort schreiben kann. Ich wollte dies jedoch für die Community öffnen, da ich dachte, dies wäre eine gute Frage für ProgrammersSE. ;-)
S.Robins
0

Schauen Sie sich meine Antwort auf diese Frage an: Wie richte ich MVP für eine Winforms-Lösung ein?

Ich habe tatsächlich eine Beispielanwendung geschrieben, die zeigt, wie ich meine GUI überlagere und teste.

Bearbeiten lesen: Verwenden Sie einen Test-Runner, der sich in Ihre Entwicklungsumgebung einfügt. Ich benutze ReSharper.

Bryan Boettcher
quelle
Vielen Dank für die ReSharper-Empfehlung. Dies ist ein Tool, das ich beim Entwickeln benutze. Leider hilft es nicht, wenn die Tests auf dem Integrations-Build-Server ausgeführt werden. Es sagt mir auch nicht, wie Nunit-Tests konfiguriert werden müssen, um beim Testen auf Code in einer Exe zuzugreifen.
S.Robins
1
Informell ist es so. Die exe ist nur die Ansicht, die den Presenter, die Modelle und die Ansichtsmodelle aus einer Klassenbibliothek als Teil des Anwendungsstarts lädt. Zumindest in meiner Lösung ist die Ansicht so dumm, dass wir sie nicht mit automatisierten Tests testen und nur Akzeptanztests durchführen, um sicherzustellen, dass die Dinge richtig geschrieben sind und die Schaltflächen dort sind, wo sie sein sollten. Das Testen einer DLL mit NUnit ist sehr einfach.
Bryan Boettcher
0

Ich hatte vor ein paar Jahren Nunit WinForms geschrieben (6 Jahre, denke ich). Eine Sache, an die ich mich besonders erinnere, ist, dass es sich zwar um einen Einzeltestfall handelt, aber auch als End-to-End-Testfall. Manchmal gibt es auf einem Frontend (einem einfachen Formular) nicht viel zu testen. Auch wenn Sie versuchen, ein Meldungsfeld zu testen, das bei einem Tastenklick angezeigt wird, testen Sie versehentlich verschiedene andere Methoden aus anderen Layern. Es gibt einige Dinge, die Sie nicht so gut automatisieren können. Das Erscheinungsbild und die Benutzerfreundlichkeit können nicht mithilfe automatisierter Komponententests automatisiert werden. Sie müssen vor der Veröffentlichung einige manuelle Tests durchführen.

ViSu
quelle
Wenn Ihr Kunde angibt, dass ein Bildschirm in einer bestimmten Weise aussehen oder sich in einer bestimmten Weise ändern soll, sollten Sie in der Lage sein, diese Dinge zu testen. Das Erfassen von Spezifikationen als Tests ist das Herzstück der BDD-Methodik, und ich habe noch nie eine Situation gefunden, in der Sie - wenn auch kreativ - keine Möglichkeit gefunden haben, einen Test zu automatisieren. Die eigentliche Frage ist, ob das Testen von Wert ist, ob die Anwendung so gut berücksichtigt ist, dass Sie alle Tests überhaupt automatisieren können und ob die Tests kostengünstig sind. Ich stimme jedoch zu, dass dies manchmal nicht der Fall ist.
S.Robins