Also habe ich in einer Organisation gearbeitet, die Entwickler ziemlich unter Druck setzt, Unit-Tests zu schreiben und zu warten. Obwohl ich in der Vergangenheit nicht viel getan habe, mag ich die Idee und glaube, dass jedes seriöse Projekt ein gewisses Maß an Komponententests haben sollte, besonders für Self-Container-Klassenbibliotheken, die sich für solche Tests eignen.Verschleiern Einheitentests unnötigerweise den Code oder gibt es einen besseren Weg?
Allerdings habe ich auch festgestellt, dass der einst sehr einfache, lesbare Code zu einer Ungeheuerlichkeit von Fabriken und Interfaces wurde. Am einfachsten Fall ein Service-Wrapper:
Keine Einheit testet
class ShazamService
{
private string url;
public ShazamService(string url) { this.url = url; }
string IdentifySong(byte [] mp3Data)
{
return HttpHelper.Upload(url, mp3Data).Response;
}
}
class Program
{
public static int Main(string [] args)
{
var svc = new ShazamService("http://www.shazam.com");
Console.Writeline(svc.IdentifySong(args[0].ToByteArray());
}
}
Einheit testbare Version
public interface IShazamService
{
public string IdentifySong(byte [] mp3Data);
}
public class ShazamClassFactory
{
private string url;
public ShazamClassFactory(string url) { this.url = url; }
public IShazamService GetInstance(bool test)
{
if (test)
{
return new ShazamServiceTest(this.url);
}
else
{
return new ShazamService(this.url);
}
}
class ShazamService
{
private string url;
public ShazamService(string url) { this.url = url; }
string IdentifySong(byte [] mp3Data)
{
return HttpHelper.Upload(url, mp3Data).Response;
}
}
class Program
{
public static int Main(string [] args)
{
var factory = new ShazamClassFactory("http://www.shazam.com");
var svc = factory.GetInstance(false);
Console.Writeline(svc.IdentifySong(args[0].ToByteArray());
}
}
ist nicht nur der Code signifikant länger in dem zweiten ein, aber (für mich) ist es weniger klar - von Main kenne ich nicht einmal den Typ des Rückgabewerts von CreateInstance, wenn ich mir ein Implementierungsdetail ansehen muss, damit ich nicht so einfach F12 durch die Logik gehen kann. Auch, was 1 Datei für den Service gewesen wäre, wird jetzt 4 (Fabrik, Schnittstelle, 2 Implementierungen), mit Header, Dokumentation usw. Schließlich, wenn ich entscheide, dass ich den Konstruktor von string url
zu string url, SongGenre genre
ändern möchte, muss ich jetzt überprüfen aus, aktualisieren und checken 4 separate Dateien ein und aktualisieren Konstruktoren, Datenmember, Dokumentation usw. für jeden.
Ist diese Methode zur Förderung von Unit-Tests die Norm? Gibt es weniger aufdringliche Optionen? Und, ist es das wert? Meiner Ansicht nach erhöht sich durch die Verkomplizierung des Codes die Entwicklungszeit, und Fehler werden wahrscheinlicher, indem sie sich mit unechten Objekten testen, die den Code, den Sie verwenden, nur sorta-irgendwie testen.
Dies hat nichts mit Unit-Tests zu tun, nicht sicher, wo Sie herkommen mit dieser Fabrik und das ist schrecklich wenn es drin ist. Das ist nur schlechtes Design, es hat nichts mit Unit-Tests zu tun. –
Das Codieren zu Interfaces und nicht zu konkreten Klassen ermöglicht flexibleren Code, unabhängig vom Komponententest. Um die hässliche Fabrik mit einem Bool-Parameter zu vermeiden, möchten Sie vielleicht IoC betrachten, so dass Sie all dies in einer Konfigurationsdatei einstellen können, anstatt Ihren Code zu überladen. – DeanOC
Kurze Antwort: Komponententests sollten nicht dazu führen, dass der Code stärker ausgelutscht wird. Finden Sie heraus, was Ihr Test braucht, um zu verhöhnen, und machen Sie es möglich, das zu übergeben. In diesem Fall, frex, anstatt "HttpHelper.Upload" hart zu codieren, könnten Sie einen "Upload" -Delegaten übergeben. Wenn Sie das nicht ständig tun möchten, können Sie zwei Konstruktoren haben, einen (zum Testen), der den Delegaten übernimmt und einen, der ihn fest codiert. Ich schlage vor, eine andere Frage zu stellen, "wie mache ich das testbar?" –