it-swarm.com.de

Sollten wir unseren Code von Anfang an so gestalten, dass Unit-Tests möglich sind?

In unserem Team wird derzeit diskutiert, ob das Ändern des Code-Designs, um Unit-Tests zu ermöglichen, ein Code-Geruch ist oder inwieweit dies ohne Code-Geruch möglich ist. Dies ist darauf zurückzuführen, dass wir gerade erst damit beginnen, Praktiken einzuführen, die in nahezu jedem anderen Softwareentwicklungsunternehmen vorhanden sind.

Insbesondere werden wir einen Web-API-Service haben, der sehr dünn sein wird. Die Hauptverantwortung besteht darin, Webanfragen/-antworten zu sammeln und eine zugrunde liegende API aufzurufen, die die Geschäftslogik enthält.

Ein Beispiel ist, dass wir planen, eine Factory zu erstellen, die einen Authentifizierungsmethoden-Typ zurückgibt. Wir brauchen keine Schnittstelle zu erben, da wir nicht davon ausgehen, dass es sich jemals um etwas anderes als den konkreten Typ handelt. Um den Web-API-Dienst zu testen, müssen wir diese Factory jedoch verspotten.

Dies bedeutet im Wesentlichen, dass wir entweder die Web-API-Controller-Klasse so entwerfen, dass sie DI akzeptiert (über ihren Konstruktor oder Setter). Dies bedeutet, dass wir einen Teil des Controllers so entwerfen, dass DI zulässig ist und eine Schnittstelle implementiert wird, die wir sonst nicht benötigen, oder dass wir sie verwenden Ein Framework von Drittanbietern wie Ninject, um zu vermeiden, dass der Controller auf diese Weise entworfen werden muss. Wir müssen jedoch noch eine Schnittstelle erstellen.

Einige im Team scheinen nur ungern Code zu entwerfen, nur um ihn zu testen. Es scheint mir, dass es einen Kompromiss geben muss, wenn Sie einen Unit-Test durchführen möchten, aber ich bin mir nicht sicher, wie ich ihre Bedenken zerstreuen soll.

Um ganz klar zu sein, dies ist ein brandneues Projekt. Es geht also nicht wirklich darum, Code zu ändern, um Unit-Tests zu ermöglichen. Es geht darum, den Code, den wir schreiben werden, so zu gestalten, dass er auf Einheiten getestet werden kann.

92
Lee

Die Zurückhaltung, Code zum Testen zu ändern, zeigt, dass ein Entwickler die Rolle von Tests und implizit seine eigene Rolle in der Organisation nicht verstanden hat.

Das Softwaregeschäft dreht sich um die Bereitstellung einer Codebasis, die Geschäftswert schafft. Wir haben durch langjährige und bittere Erfahrung festgestellt, dass wir solche Codebasen von nicht trivialer Größe nicht ohne Tests erstellen können. Daher sind Testsuiten ein wesentlicher Bestandteil des Geschäfts.

Viele Programmierer bekennen sich zu diesem Prinzip, akzeptieren es aber unbewusst nie. Es ist leicht zu verstehen, warum dies so ist; Das Bewusstsein, dass unsere eigenen mentalen Fähigkeiten nicht unendlich sind und in der Tat überraschend begrenzt sind, wenn man mit der enormen Komplexität einer modernen Codebasis konfrontiert wird, ist unerwünscht und kann leicht unterdrückt oder rationalisiert werden. Die Tatsache, dass der Testcode nicht an den Kunden geliefert wird, macht es leicht zu glauben, dass er ein Bürger zweiter Klasse ist und im Vergleich zum "wesentlichen" Geschäftscode nicht wesentlich ist. Und die Idee, Testcode zum Geschäftscode hinzuzufügen, erscheint vielen doppelt beleidigend.

Das Problem bei der Rechtfertigung dieser Praxis hat damit zu tun, dass das gesamte Bild der Wertschöpfung in einem Softwaregeschäft oft nur von höheren Stellen in der Unternehmenshierarchie verstanden wird, diese Personen jedoch nicht über das detaillierte technische Verständnis verfügen Der Codierungsworkflow, der zum Verstehen von warum Tests erforderlich ist, kann nicht entfernt werden. Daher werden sie zu oft von Praktizierenden beruhigt, die ihnen versichern, dass das Testen im Allgemeinen eine gute Idee sein kann. aber "Wir sind Elite-Programmierer, die solche Krücken nicht brauchen" oder "wir tun es nicht". Ich habe jetzt keine Zeit dafür "usw. usw. Die Tatsache, dass Geschäftserfolg ein Spiel mit Zahlen ist und dass die Vermeidung technischer Schulden, die Sicherung der Qualität usw. nur auf längere Sicht ihren Wert zeigt, bedeutet, dass sie in dieser Überzeugung oft recht aufrichtig sind .

Lange Rede, kurzer Sinn: Das Testen von Code ist ein wesentlicher Bestandteil des Entwicklungsprozesses, nicht anders als in anderen Bereichen (viele Mikrochips sind mit einem erheblichen Anteil an Elementen ausgelegt nur zu Testzwecken), aber es ist sehr einfach die sehr guten Gründe dafür zu übersehen. Fallen Sie nicht in diese Falle.

203
Kilian Foth

Es ist nicht so einfach, wie Sie vielleicht denken. Lassen Sie es uns zusammenfassen.

  • Unit-Tests zu schreiben ist definitiv eine gute Sache.

ABER!

  • Jede Änderung an Ihrem Code kann einen Fehler verursachen. Eine Änderung des Codes ohne guten Geschäftsgrund ist daher keine gute Idee.

  • Ihr "sehr dünnes" Webapi scheint nicht der beste Fall für Unit-Tests zu sein.

  • Das gleichzeitige Ändern von Code und Tests ist eine schlechte Sache.

Ich würde den folgenden Ansatz vorschlagen:

  1. Schreiben Sie Integrationstests . Dies sollte keine Codeänderungen erfordern. Sie erhalten Ihre grundlegenden Testfälle und können überprüfen, ob weitere Codeänderungen keine Fehler verursachen.

  2. Stellen Sie sicher, dass neuer Code testbar ist und Unit- und Integrationstests enthält.

  3. Stellen Sie sicher, dass Ihre CI-Kette nach Builds und Bereitstellungen Tests ausführt.

Wenn Sie diese Dinge eingerichtet haben, sollten Sie erst dann darüber nachdenken, ältere Projekte auf Testbarkeit umzugestalten.

Hoffentlich hat jeder Lehren aus dem Prozess gezogen und eine gute Vorstellung davon, wo Tests am dringendsten benötigt werden, wie Sie sie strukturieren möchten und welchen Wert sie für das Unternehmen haben.

EDIT : Seit ich diese Antwort geschrieben habe, hat das OP die Frage geklärt, um zu zeigen, dass es sich um neuen Code handelt, nicht um Änderungen an vorhandenem Code. Ich dachte vielleicht naiv: "Ist Unit-Test gut?" Streit wurde vor einigen Jahren beigelegt.

Es ist schwer vorstellbar, welche Codeänderungen für Unit-Tests erforderlich wären, aber keine allgemeine bewährte Methode, die Sie auf jeden Fall wünschen würden. Es wäre wahrscheinlich ratsam, die tatsächlichen Einwände zu untersuchen, möglicherweise wird der Stil der Einheitentests beanstandet.

75
Ewan

Das Entwerfen von Code, der von Natur aus testbar ist, ist kein Codegeruch. im Gegenteil, es ist das Zeichen eines guten Designs. Auf dieser Grundlage gibt es mehrere bekannte und weit verbreitete Entwurfsmuster (z. B. Model-View-Presenter), die einfache (einfachere) Tests als großen Vorteil bieten.

Wenn Sie also eine Schnittstelle für Ihre konkrete Klasse schreiben müssen, um sie einfacher testen zu können, ist das eine gute Sache. Wenn Sie bereits über die konkrete Klasse verfügen, können die meisten IDEs eine Schnittstelle daraus extrahieren, wodurch der Aufwand minimal ist. Es ist ein bisschen mehr Arbeit, die beiden synchron zu halten, aber eine Benutzeroberfläche sollte sich sowieso nicht viel ändern, und die Vorteile des Testens können diesen zusätzlichen Aufwand überwiegen.

Auf der anderen Seite als @MatthieuM. In einem Kommentar erwähnt, könnte dies ein Problem sein, wenn Sie Ihrem Code bestimmte Einstiegspunkte hinzufügen, die niemals in der Produktion verwendet werden sollten, nur zu Testzwecken.

18
mmathis

Es ist meiner Meinung nach sehr einfach zu verstehen, dass der zu testende Code zum Erstellen von Komponententests mindestens bestimmte Eigenschaften haben muss. Wenn der Code beispielsweise nicht aus einzelne Einheiten besteht, die isoliert getestet werden können, macht das Wort "Unit-Test" nicht einmal Sinn. Wenn der Code diese Eigenschaften nicht hat, muss er zuerst geändert werden, das ist ziemlich offensichtlich.

Theoretisch kann man versuchen, zuerst eine testbare Codeeinheit zu schreiben, indem man alle SOLID -Prinzipien) anwendet und anschließend versucht, einen Test dafür zu schreiben, ohne den ursprünglichen Code weiter zu modifizieren. Leider ist das Schreiben von Code, der wirklich Unit-testbar ist, nicht immer ganz einfach. Daher ist es sehr wahrscheinlich, dass einige Änderungen erforderlich sind, die nur beim Versuch, die Tests zu erstellen, erkannt werden. Dies gilt auch für Code, der mit der Idee geschrieben wurde im Hinblick auf Unit-Tests, und es ist definitiv wahrer für Code, der geschrieben wurde, wo "Unit-Testbarkeit" zu Beginn nicht auf der Tagesordnung stand.

Es gibt einen bekannten Ansatz, der versucht, das Problem zu lösen, indem zuerst die Komponententests geschrieben werden. Er heißt Test Driven Development (TDD) und kann sicherlich dazu beitragen, Code von Anfang an einheitlicher testbar zu machen.

Natürlich tritt die Zurückhaltung, Code nachträglich zu ändern, um ihn testbar zu machen, häufig in einer Situation auf, in der der Code zuerst manuell getestet wurde und/oder in der Produktion einwandfrei funktioniert. Wenn Sie ihn also ändern, kann dies tatsächlich zu neuen Fehlern führen. Der beste Ansatz, um dies zu mildern, besteht darin, zuerst eine Regressionstestsuite zu erstellen (die häufig mit nur sehr geringen Änderungen an der Codebasis implementiert werden kann) sowie andere begleitende Maßnahmen wie Codeüberprüfungen oder neue manuelle Testsitzungen. Das sollte Ihnen genug Vertrauen geben, um sicherzustellen, dass die Neugestaltung einiger Interna nichts Wichtiges zerstört.

13
Doc Brown

Ich habe Probleme mit der (unbegründeten) Behauptung, die Sie machen:

um den Web-API-Dienst zu testen, müssen wir diese Factory verspotten

Das ist nicht unbedingt wahr. Es gibt viele Möglichkeiten, Tests zu schreiben, und es gibt sind Möglichkeiten, Unit-Tests zu schreiben, die keine Verspottungen beinhalten. Noch wichtiger ist, dass es andere Arten von Tests gibt, wie z. B. Funktions- oder Integrationstests. Oft ist es möglich, eine "Testnaht" an einer "Schnittstelle" zu finden, die keine OOP Programmiersprache interface ist.

Einige Fragen, die Ihnen helfen sollen, eine alternative Testnaht zu finden, die möglicherweise natürlicher ist:

  • Möchte ich jemals eine Thin Web-API über eine andere API schreiben?
  • Kann ich die Codeduplizierung zwischen der Web-API und der zugrunde liegenden API reduzieren? Kann eins in Bezug auf das andere erzeugt werden?
  • Kann ich die gesamte Web-API und die zugrunde liegende API als eine einzige "Black Box" -Einheit behandeln und aussagekräftige Aussagen darüber machen, wie sich das Ganze verhält?
  • Wenn die Web-API in Zukunft durch eine neue Implementierung ersetzt werden müsste, wie würden wir das tun?
  • Wenn die Web-API in Zukunft durch eine neue Implementierung ersetzt würde, könnten Clients der Web-API dies bemerken? Wenn das so ist, wie?

Eine weitere unbegründete Behauptung, die Sie machen, betrifft DI:

entweder entwerfen wir die Web-API-Controller-Klasse so, dass sie DI akzeptiert (über ihren Konstruktor oder Setter), was bedeutet, dass wir einen Teil des Controllers so entwerfen, dass DI zulässig ist und eine Schnittstelle implementiert wird, die wir sonst nicht benötigen, oder wir verwenden einen Dritten Framework wie Ninject, um zu vermeiden, dass der Controller auf diese Weise entworfen werden muss, aber wir müssen trotzdem eine Schnittstelle erstellen.

Abhängigkeitsinjektion bedeutet nicht unbedingt, dass ein neues interface erstellt wird. Beispiel für die Ursache eines Authentifizierungstokens: Können Sie einfach programmgesteuert ein real Authentifizierungstoken erstellen? Dann kann der Test solche Token erstellen und injizieren. Hängt der Prozess zur Validierung eines Tokens von einem kryptografischen Geheimnis ab? Ich hoffe, Sie haben kein Geheimnis fest codiert - ich würde erwarten, dass Sie es irgendwie aus dem Speicher lesen können, und in diesem Fall können Sie einfach ein anderes (bekanntes) Geheimnis in Ihren Testfällen verwenden.

Dies bedeutet nicht, dass Sie niemals ein neues interface erstellen sollten. Aber lassen Sie sich nicht darauf fixieren, dass es nur eine Möglichkeit gibt, einen Test zu schreiben oder ein Verhalten vorzutäuschen. Wenn Sie über den Tellerrand hinaus denken, finden Sie normalerweise eine Lösung, die ein Minimum an Verzerrungen Ihres Codes erfordert und dennoch den gewünschten Effekt erzielt.

11
Daniel Pryden

Sie haben Glück, denn dies ist ein neues Projekt. Ich habe festgestellt, dass Test Driven Design sehr gut zum Schreiben von gutem Code geeignet ist (weshalb wir dies in erster Linie tun).

Indem Sie herausfinden, im Voraus , wie Sie einen bestimmten Code mit realistischen Eingabedaten aufrufen und dann realistische Ausgabedaten erhalten, die Sie überprüfen können, wie beabsichtigt, tun Sie das API-Design sehr früh im Prozess und haben gute Chancen, ein nützliches Design zu erhalten, da Sie nicht durch vorhandenen Code behindert werden, der neu geschrieben werden muss, um sich anzupassen. Außerdem ist es für Ihre Kollegen einfacher zu verstehen, sodass Sie zu Beginn des Prozesses wieder gute Diskussionen führen können.

Beachten Sie, dass "nützlich" im obigen Satz nicht nur bedeutet, dass die resultierenden Methoden leicht aufzurufen sind, sondern auch, dass Sie dazu neigen, saubere Schnittstellen zu erhalten, die sich leicht in Integrationstests aufbauen lassen, und für die Sie Modelle schreiben können.

Denke darüber nach. Besonders bei Peer Review. Nach meiner Erfahrung wird sich die Investition von Zeit und Mühe sehr schnell amortisieren.

Wenn Sie den Code ändern müssen, ist dies der Codegeruch.

Aus persönlicher Erfahrung ist es ein schlechter Code, wenn es schwierig ist, Tests für meinen Code zu schreiben. Es ist kein schlechter Code, weil er nicht wie geplant ausgeführt wird oder funktioniert. Es ist schlecht, weil ich nicht schnell verstehen kann, warum er funktioniert. Wenn ich auf einen Fehler stoße, weiß ich, dass es eine lange schmerzhafte Aufgabe sein wird, ihn zu beheben. Der Code ist auch schwierig/unmöglich wiederzuverwenden.

Guter (sauberer) Code unterteilt Aufgaben in kleinere Abschnitte, die auf einen Blick leicht verständlich sind (oder zumindest gut aussehen). Das Testen dieser kleineren Abschnitte ist einfach. Ich kann auch Tests schreiben, die nur dann einen Teil der Codebasis mit ähnlicher Leichtigkeit testen, wenn ich ziemlich sicher bin, was die Unterabschnitte angeht (die Wiederverwendung hilft auch hier, da sie bereits getestet wurde).

Halten Sie den Code von Anfang an einfach zu testen, einfach umzugestalten und einfach wiederzuverwenden, und Sie werden sich nicht umbringen, wenn Sie Änderungen vornehmen müssen.

Ich schreibe dies, während ich ein Projekt komplett neu erstelle, das ein Wegwerfprototyp in saubereren Code hätte sein sollen. Es ist viel besser, es von Anfang an richtig zu machen und schlechten Code so schnell wie möglich umzugestalten, als stundenlang auf einen Bildschirm zu starren, weil man Angst hat, etwas zu berühren, aus Angst, etwas zu beschädigen, das teilweise funktioniert.

8
David

Ich würde argumentieren, dass das Schreiben von Code, der nicht Unit-getestet werden kann, ein Code-Geruch ist. Wenn Ihr Code nicht einheitlich getestet werden kann, ist er im Allgemeinen nicht modular aufgebaut, was es schwierig macht, ihn zu verstehen, zu warten oder zu verbessern. Wenn es sich bei dem Code um Klebercode handelt, der nur im Hinblick auf Integrationstests wirklich Sinn macht, können Sie möglicherweise Unit-Tests durch Integrationstests ersetzen. Selbst dann, wenn die Integration fehlschlägt, müssen Sie das Problem eingrenzen, und Unit-Tests sind eine gute Möglichkeit Tu es.

Du sagst

Wir planen, eine Factory zu erstellen, die einen Authentifizierungsmethoden-Typ zurückgibt. Wir brauchen keine Schnittstelle zu erben, da wir nicht davon ausgehen, dass es sich jemals um etwas anderes als den konkreten Typ handelt. Um den Web-API-Dienst zu testen, müssen wir diese Factory jedoch verspotten.

Ich folge dem nicht wirklich. Der Grund für eine Fabrik, die etwas erstellt, besteht darin, dass Sie Fabriken ändern oder das, was die Fabrik erstellt, einfach ändern können, sodass andere Teile des Codes nicht geändert werden müssen. Wenn sich Ihre Authentifizierungsmethode niemals ändern wird, ist die werksseitige Code-Aufblähung nutzlos. Wenn Sie jedoch im Test eine andere Authentifizierungsmethode als in der Produktion haben möchten, ist eine Factory, die im Test eine andere Authentifizierungsmethode als in der Produktion zurückgibt, eine großartige Lösung.

Sie benötigen hierfür weder DI noch Mocks. Sie benötigen lediglich Ihre Factory, um die verschiedenen Authentifizierungstypen zu unterstützen und irgendwie konfigurierbar zu sein, z. B. aus einer Konfigurationsdatei oder einer Umgebungsvariablen.

4
Old Pro

In jeder Ingenieurdisziplin, die ich mir vorstellen kann, gibt es nur einen Weg, um ein anständiges oder höheres Qualitätsniveau zu erreichen:

Berücksichtigung von Inspektionen/Tests im Design.

Dies gilt für Konstruktion, Chipdesign, Softwareentwicklung und Fertigung. Das bedeutet nicht, dass das Testen die Säule ist, um die sich jedes Design drehen muss, überhaupt nicht. Bei jeder Entwurfsentscheidung müssen die Designer jedoch klar über die Auswirkungen auf die Testkosten sein und bewusste Entscheidungen über den Kompromiss treffen.

In einigen Fällen sind manuelle oder automatisierte Tests (z. B. Selen) bequemer als Unit-Tests und bieten gleichzeitig eine akzeptable Testabdeckung für sich. In seltenen Fällen kann es auch akzeptabel sein, etwas zu werfen, das fast völlig ungetestet ist. Diese müssen jedoch von Fall zu Fall bewusst sein. Das Aufrufen eines Designs, das das Testen eines "Codegeruchs" berücksichtigt, weist auf einen ernsthaften Mangel an Erfahrung hin.

2
Peter

Dies bedeutet im Wesentlichen, dass wir entweder die Web-API-Controller-Klasse so entwerfen, dass sie DI akzeptiert (über ihren Konstruktor oder Setter). Dies bedeutet, dass wir einen Teil des Controllers so entwerfen, dass DI zulässig ist und eine Schnittstelle implementiert wird, die wir sonst nicht benötigen, oder dass wir sie verwenden Ein Framework von Drittanbietern wie Ninject, um zu vermeiden, dass der Controller auf diese Weise entworfen werden muss. Wir müssen jedoch noch eine Schnittstelle erstellen.

Schauen wir uns den Unterschied zwischen einem testbaren an:

public class MyController : Controller
{
    private readonly IMyDependency _thing;

    public MyController(IMyDependency thing)
    {
        _thing = thing;
    }
}

und nicht testbarer Controller:

public class MyController : Controller
{
}

Die erstere Option enthält buchstäblich 5 zusätzliche Codezeilen, von denen zwei von Visual Studio automatisch generiert werden können. Sobald Sie Ihr Abhängigkeitsinjektionsframework so eingerichtet haben, dass es zur Laufzeit IMyDependency durch einen konkreten Typ ersetzt - was für jedes anständige DI-Framework eine weitere einzelne Codezeile ist -, funktioniert alles nur, außer jetzt können Sie es verspotten und somit testen Ihr Controller nach Herzenslust.

6 zusätzliche Codezeilen, um Testbarkeit zu ermöglichen ... und Ihre Kollegen argumentieren, dass dies "zu viel Arbeit" ist? Dieses Argument fliegt nicht mit mir und sollte nicht mit dir fliegen.

Und Sie müssen keine Schnittstelle zum Testen erstellen und implementieren: Moq ermöglicht es Ihnen beispielsweise, das zu simulieren Verhalten eines konkreten Typs für Unit-Test-Zwecke. Das nützt Ihnen natürlich nicht viel, wenn Sie diese Typen nicht in die Klassen einfügen können, die Sie testen.

Die Abhängigkeitsinjektion ist eines der Dinge, bei denen Sie sich fragen, wie ich ohne das gearbeitet habe, wenn Sie es einmal verstanden haben. Es ist einfach, es ist effektiv und es macht nur Sinn. Bitte lassen Sie nicht zu, dass das mangelnde Verständnis Ihrer Kollegen für neue Dinge Ihr Projekt testbar macht.

1
Ian Kemp

Ich habe festgestellt, dass Unit-Tests (und andere Arten von automatisierten Tests) dazu neigen, Code-Gerüche zu reduzieren, und ich kann mir kein einziges Beispiel vorstellen, in dem sie Code-Gerüche einführen. Unit-Tests zwingen Sie normalerweise dazu, besseren Code zu schreiben. Wenn Sie eine zu testende Methode nicht einfach verwenden können, warum sollte sie in Ihrem Code einfacher sein?

Gut geschriebene Unit-Tests zeigen Ihnen, wie der Code verwendet werden soll. Sie sind eine Form der ausführbaren Dokumentation. Ich habe schrecklich geschriebene, zu lange Unit-Tests gesehen, die einfach nicht verstanden werden konnten. Schreib die nicht! Wenn Sie lange Tests schreiben müssen, um Ihre Klassen einzurichten, müssen Ihre Klassen umgestaltet werden.

Unit-Tests zeigen, wo sich einige Ihrer Code-Gerüche befinden. Ich würde empfehlen, Michael C. Feathers 'Effektiv mit Legacy Code arbeiten zu lesen. Obwohl Ihr Projekt neu ist, benötigen Sie möglicherweise einige nicht offensichtliche Techniken, um Ihren Code zum Testen zu bringen, wenn es noch keine (oder viele) Komponententests enthält.

1
CJ Dennis

In einer Nussschale:

Testbarer Code ist (normalerweise) wartbarer Code - oder besser gesagt, Code, der schwer zu testen ist, ist normalerweise schwer zu warten. Das Entwerfen von Code, der nicht testbar ist, ähnelt dem Entwerfen einer Maschine, die nicht reparierbar ist - schade, dass der arme Shmuck wird beauftragt ist, ihn irgendwann zu reparieren (vielleicht sind Sie es).

Ein Beispiel ist, dass wir planen, eine Factory zu erstellen, die einen Authentifizierungsmethoden-Typ zurückgibt. Wir brauchen keine Schnittstelle zu erben, da wir nicht davon ausgehen, dass es sich jemals um etwas anderes als den konkreten Typ handelt.

Sie wissen, dass Sie in drei Jahren fünf verschiedene Arten von Authentifizierungsmethoden benötigen, nachdem Sie das gesagt haben, oder? Die Anforderungen ändern sich, und obwohl Sie vermeiden sollten, Ihr Design zu überarbeiten, bedeutet ein testbares Design, dass Ihr Design (gerade) genug Nähte hat, um (auch) geändert zu werden viel) Schmerz - und dass die Modultests Ihnen automatisierte Mittel bieten, um zu sehen, dass Ihre Änderungen nichts kaputt machen.

1
CharonX

Das Entwerfen um die Abhängigkeitsinjektion ist kein Codegeruch - es ist eine bewährte Methode. Die Verwendung von DI dient nicht nur der Testbarkeit. Wenn Sie Ihre Komponenten auf DI aufbauen, können Sie die Modularität und Wiederverwendbarkeit verbessern und wichtige Komponenten einfacher austauschen (z. B. eine Datenbankschnittstellenschicht). Während es ein gewisses Maß an Komplexität hinzufügt, ermöglicht es bei richtiger Ausführung eine bessere Trennung von Ebenen und eine Isolierung von Funktionen, wodurch die Komplexität einfacher zu verwalten und zu navigieren ist. Dies erleichtert die ordnungsgemäße Überprüfung des Verhaltens jeder Komponente, wodurch Fehler reduziert und das Auffinden von Fehlern erleichtert werden.

1
Zenilogix

Wenn ich Unit-Tests schreibe, denke ich darüber nach, was in meinem Code schief gehen könnte. Es hilft mir, das Code-Design zu verbessern und das Single Responsibility-Prinzip (SRP) anzuwenden. Wenn ich einige Monate später zurückkomme, um denselben Code zu ändern, kann ich außerdem bestätigen, dass vorhandene Funktionen nicht fehlerhaft sind.

Es gibt einen Trend, so viele reine Funktionen wie möglich zu verwenden (serverlose Apps). Unit-Tests helfen mir, den Status zu isolieren und reine Funktionen zu schreiben.

Insbesondere werden wir einen Web-API-Service haben, der sehr dünn sein wird. Die Hauptverantwortung besteht darin, Webanfragen/-antworten zu sammeln und eine zugrunde liegende API aufzurufen, die die Geschäftslogik enthält.

Schreiben Sie zuerst Komponententests für die zugrunde liegende API. Wenn Sie über ausreichend Entwicklungszeit verfügen, müssen Sie auch Tests für den Thin Web API-Dienst schreiben.

TL; DR, Unit-Tests tragen zur Verbesserung der Codequalität bei und helfen dabei, zukünftige Änderungen am Code risikofrei vorzunehmen. Es verbessert auch die Lesbarkeit des Codes. Verwenden Sie Tests anstelle von Kommentaren, um Ihren Standpunkt zu verdeutlichen.

0
Ashutosh

Das Fazit und was Sie mit dem widerstrebenden Los argumentieren sollten, ist, dass es keinen Konflikt gibt. Der große Fehler scheint gewesen zu sein, dass jemand die Idee geprägt hat, Menschen, die das Testen hassen, "zum Testen zu entwerfen". Sie hätten einfach den Mund halten oder es anders ausdrücken sollen, wie "Nehmen wir uns die Zeit, dies richtig zu machen".

Die Idee, dass "Sie eine Schnittstelle implementieren müssen", um etwas testbar zu machen, ist falsch. Die Schnittstelle ist bereits implementiert, sie ist nur noch nicht in der Klassendeklaration deklariert. Es geht darum, vorhandene öffentliche Methoden zu erkennen, ihre Signaturen auf eine Schnittstelle zu kopieren und diese Schnittstelle in der Deklaration der Klasse zu deklarieren. Keine Programmierung, keine Änderungen an der vorhandenen Logik.

Anscheinend haben einige Leute eine andere Vorstellung davon. Ich schlage vor, Sie versuchen zuerst, dies zu beheben.

0
Martin Maat