Wo immer möglich, ich TDD verwenden:ohne Code von Testabdeckung
- ich meine Schnittstellen verspotten
- ich IOC verwenden, so kann meine verspottet ojbects
- injiziert werden, ich meine Tests sicherzustellen laufen und dass die Abdeckung steigt und ich bin glücklich.
dann ...
- I create Klassen abgeleitet, die tatsächlich Dinge zu tun, wie in einer Datenbank, oder das Schreiben an eine Nachrichtenwarteschlange usw.
Dies ist, wo Code-Coverage nimmt ab - und ich bin traurig.
Aber dann verbreite ich großzügig [CoverageExclude]
über diese konkreten Klassen und Abdeckung geht wieder hoch.
Aber dann fühle ich mich nicht traurig, sondern schmutzig. Ich habe irgendwie das Gefühl zu betrügen, obwohl es nicht möglich ist, die konkreten Klassen zu testen.
Ich bin interessiert zu hören, wie Ihre Projekte organisiert sind, das heißt, wie Sie ordnen Sie körperlich Code dass kann gegen Code getestet werden, die nicht getestet werden.
Ich denke, dass eine nette Lösung wäre, untestable Betontypen in ihre eigene Baugruppe zu trennen und dann die Verwendung von [CoverageExclude]
in den Baugruppen zu verbieten, die testbaren Code enthalten. Dies würde es auch einfacher machen, eine NDepend-Regel zu erstellen, die das Build fehlschlägt, wenn dieses Attribut in den testbaren Assemblys nicht korrekt gefunden wird.
Edit: die Essenz dieser Frage berührt die Tatsache, dass man die Dinge testen können, die Ihre verspottet Schnittstellen verwenden, aber Sie können nicht UNIT-Test die Objekte, die die real sind (oder sollte nicht!) Implementierungen dieser Schnittstellen. Hier ein Beispiel:
public void ApplyPatchAndReboot()
{
_patcher.ApplyPatch() ;
_rebooter.Reboot() ;
}
Patcher und rebooter werden im Konstruktor injiziert:
public SystemUpdater(IApplyPatches patcher, IRebootTheSystem rebooter)...
Die Unit-Test wie folgt aussieht:
public void should_reboot_the_system()
{
... new SystemUpdater(mockedPatcher, mockedRebooter);
update.ApplyPatchAndReboot();
}
Dies funktioniert gut - meine UNIT-Testabdeckung 100%. Ich schreibe jetzt:
Meine UNIT-TEST Abdeckung geht runter und es gibt keine Möglichkeit zu UNIT-TEST der neuen Klasse. Sicher, ich werde einen Funktionstest hinzufügen und es ausführen, wenn ich 20 Minuten übrig habe (!).
Also, ich meine meine Frage läuft darauf hinaus, dass es in der Nähe von 100% UNIT-TEST Abdeckung schön ist. Anders gesagt, es ist schön, in der Lage zu sein, 100% des Verhaltens des Systems in Einheiten zu testen. Im obigen Beispiel sollte der BEHAVIOR des Patcher den Rechner neu starten. Das können wir sicher verify
. Der Typ ReallyRebootTheSytemForReal
ist nicht nur Verhalten - es hat Nebenwirkungen, was bedeutet, dass es nicht Unit-getestet werden kann. Da es kein Unit-Test sein kann, wirkt sich dies auf den Testabdeckungsprozentsatz aus.Also,
- Ist es wichtig, dass diese Dinge Unit-Test-Abdeckung Percentage reduzieren?
- Sollten sie in ihre eigenen Baugruppen getrennt werden, wo die Leute 0% UNIT-TEST Abdeckung erwarten?
- Sollten Typen Betons wie diese so klein sein (in zyklomatische Komplexität), dass ein Unit-Test (oder anderweitig)
Was meinst du mit "kann nicht getestet werden" ?? Was sind die Barrieren? – Juri
Dinge wie bestimmte Implementierungen einer Schnittstelle, die unantastbare Bereiche berühren, wie Nachrichtenwarteschlangen, Datenbanken, das Dateisystem usw. Zum Beispiel kann eine Schnittstelle wie IWriteToAQueue verspottet werden und alle Bits, die eine IWriteToAQueue erwarten, können mit dem Mock getestet werden. Aber - der konkrete Typ namens "WriteToMsmq", der gerade in MSMQ schreibt, kann nicht Unit-getestet werden. –