Ein bisschen Kontext: Früher musste ich heute einen SQL-Code aktualisieren, den ein anderer Kollege von mir bereitgestellt hatte, und da es ein ziemlich großes Skript ist, wird es als separate Datei gespeichert (die dann zur Laufzeit gelesen und ausgeführt wird). Dabei habe ich versehentlich zwei Bugs wieder eingeführt, die wir vor ein paar Monaten hatten, nämlich:
- Aus welchem Grund auch immer, die ASCII-Datei wurde in UTF-16 verschlüsselt (der Kollege hat mir die Datei per E-Mail geschickt, was sie möglicherweise verursacht hat).
- In dem Skript fehlten die ersten
SET
Anweisungen (erforderlich aufgrund einiger Treiberprobleme in der Produktion, jedoch nicht bei einer lokalen Neuinstallation).
Nachdem ich dies ungefähr eine Stunde lang (erneut) debuggt hatte, habe ich mich dazu entschlossen, einige Komponententests zu schreiben, um sicherzustellen, dass dies nie wieder vorkommt (und eine schnelle Möglichkeit, dies zu beheben, in die Bestätigungsnachricht aufzunehmen, um zukünftigen Entwicklern eine einfache Lösung zu bieten).
Als ich diesen Code drückte, kam ein anderer Kollege (der auch unser Teamleiter ist) auf mich zu und sagte mir, ich solle diese Dinge nicht noch einmal machen, weil:
"Diese Dinge gehören nicht in Unit-Tests"
"Unit-Tests sollten nur verwendet werden, um den Fluss Ihres Codes zu überprüfen"
Ich bin jetzt ziemlich konfliktreich, da ich immer noch der Meinung bin, dass das, was ich tue, nicht falsch ist, da dieser Bug in Zukunft nicht wieder eingeführt werden würde. Allerdings arbeitet dieser Kollege als Senior und kann am Ende des Tages entscheiden, was Wir verbringen unsere Zeit auf. Was soll ich machen? Liege ich falsch, wenn ich das so mache? Gilt es als schlechte Praxis?
quelle
Antworten:
Höchstwahrscheinlich sind die von Ihnen geschriebenen Tests näher an Integrations- oder Regressionstests als an Komponententests. Während die Zeile sehr unscharf sein kann und sich manchmal in Pedanterie über das, was ein Komponententest ist oder nicht, entwickelt, gehe ich zu Ihrem Kollegen zurück und frage, wo die von Ihnen geschriebenen Tests liegen sollten, da sie einen Mehrwert bieten und die Richtigkeit des Codes sicherstellen.
Ich würde mich nicht zu sehr auf das konzentrieren, was ein Komponententest ist oder nicht, und mir ist klar, dass der Test auch dann noch einen Wert haben kann, wenn es sich um einen Integrationstest handelt.
quelle
Technisch gesehen handelt es sich nicht um einen Komponententest, sondern eher um einen Validierungsschritt. Der richtige Ansatz hängt wirklich davon ab, wie Ihr Workflow aussehen muss. Ihr Teamleiter ist in Bezug auf den Zweck von Komponententests korrekt. Mein Gefühl ist, dass dies der Fall ist, wenn für eine noch zu erledigende Aufgabe das falsche Werkzeug verwendet wird. Also fang damit an:
Anhand der Beschreibung müssen Sie überprüfen, ob alle Datenbankskripts bestimmten Standards entsprechen.
Die Qualität des Quellcodes wird normalerweise mit statischen Analysewerkzeugen überprüft . Wenn Sie kein statisches Analysetool zur Validierung Ihres SQL haben, können Sie ein schnelles und unsauberes Tool erstellen, das die Überprüfung aller an dieses Tool übergebenen SQL-Dateien durchführt. Es tut nicht weh, zu überprüfen, ob es statische Analysetools gibt, die die von Ihnen angesprochenen Probleme lösen können.
Wenn Sie diesen Teil Ihrer Build-Infrastruktur hinzufügen, z. B. in Jenkins oder ähnliches, kann er auf alle SQL-Dateien in Ihrem Projekt angewendet werden.
Die Unit-Tests lösen nur das Problem für Ihre aktuelle Datei.
Das ist ziemlich einfach, Sie sprechen mit Ihrem Teamleiter. Er kann mit dem Produktbesitzer und Ihnen zusammenarbeiten, um das Risiko und den Nutzen einer Investition in das Werkzeug zu bestimmen. Wenn dies wahrscheinlich ein einmaliges Problem ist, wäre das Werkzeug wahrscheinlich zu viel des Guten. Wenn das Werkzeug zum Auffinden der größten Probleme einfach ist, lohnt es sich möglicherweise nur für die Plausibilitätsprüfung.
Ihr Teamleiter hat möglicherweise einige Ideen, die Sie (oder ich) nicht berücksichtigt haben, um das Problem besser anzugehen.
quelle
Es ist keine gute Praxis, Tests, die auf Dateien zugreifen, "Unit-Tests" zu nennen.
Leider ist es völlig unternehmensspezifisch, welche Arten von Tests es gibt und wie sie organisiert sind. Sie müssen also herausfinden, wie Ihr Unternehmen mit diesen Tests umgeht.
Wenn Sie noch keine andere Möglichkeit haben, automatisierte Tests als Komponententests durchzuführen, besteht der pragmatische Ansatz darin, die Komponententests, die eigentlich keine Komponententests sind, mit einem Präfix zu kennzeichnen, bis Sie genug davon haben, um herauszufinden, was für eine Art von Tests, die Sie tatsächlich haben / brauchen. Danach können Sie mit der Organisation beginnen.
quelle
Michael Feathers sagt dies in seinem Buch Effective Working With Legacy Code:
Hilft Ihr Test, Fehler schnell zu lokalisieren und schnell auszuführen? Wenn ja, dann mach es! Wenn nein, dann nicht! So einfach ist das!
Davon abgesehen arbeiten Sie in einem Umfeld mit anderen Menschen und müssen mit ihnen auskommen. Möglicherweise müssen Sie es auf seine Weise tun, auch wenn Sie privat nicht damit einverstanden sind.
quelle
Ich habe gelegentlich ähnliche Tests für Quellcodedateien, Konfigurationsdateien usw. geschrieben. Ich würde sie nicht Unit-Tests nennen, weil (a) sie auf das Dateisystem zugreifen und möglicherweise nicht ultraschnell sind CI-Server).
Sie könnten sie Integrationstests nennen; Mit Sicherheit sind sie dieser Perspektive näher als Unit-Tests.
Meine eigene Bezeichnung für sie ist Ressourcentests . IMHO, sie sind absolut gerechtfertigt, wenn sie jede Nacht auf einem CI-Server ausgeführt werden: Es gibt nur minimale Kosten und bei vernünftiger Verwendung wird ein klarer Mehrwert erzielt. Eine Definition von vernünftigerweise : Wenn der Test ein Problem überprüft, das ein Problem verursacht hat (z. B. die von Ihnen erwähnte Codierung).
quelle
Bei einem Unit-Test geht es darum, eine Methode oder 'Unit'-Code zu testen. Sie testen die kleinste Gruppe von Logik und Code in Ihrer Software.
Wenn Sie dies später mit anderen Einheiten verbinden, führen Sie Integrationstests durch.
Ich hoffe, Ihr Teamleiter hat Ihre Initiative gefördert und hätte alternative Vorschläge unterbreiten sollen. Sie haben definitiv die richtige Idee.
Ihr SQL ist Code wie jede Sprache niedrigerer Generation wie C # oder Java und sollte als solcher getestet werden. Verifikation und Validierung gehören zu allen Teststufen. Daher werden Codierungs- und SET-Anweisungen eingeschlossen, aber nicht unbedingt exklusiv getestet. Allgemeine Dinge wie Zeilenenden oder das Einschließen können Sie normalerweise nur mit einem SCM-Hook oder einer SCM-Funktion erledigen.
Es wird empfohlen, Regressionstests durchzuführen, um sicherzustellen, dass frühere Bugs nicht erneut auftreten. Im Allgemeinen werden Tests zusammen mit jeder Fehlerbehebung erstellt. Wenn diese Fehler nicht durch Regressionstests auf Einheiten- / Integrations- oder Systemebene abgedeckt und dann wieder eingeführt werden, handelt es sich um ein Teamproblem, ein Prozessproblem, kein individuelles Problem.
Die Sache ist ... Syntaxfehler, fehlende Anweisungen oder Logikblöcke in einer 'Einheit' werden normalerweise nicht getestet. Sie testen die Ein- und Ausgänge des Geräts in verschiedenen Kombinationen und testen die vielen Möglichkeiten, die generiert werden können.
Zurück zu den fehlenden SET-Anweisungen - Sie informieren über die zahlreichen Ein- und Ausgabemöglichkeiten, auf die getestet werden muss. Welchen Test würden Sie schreiben, der fehlschlagen würde, wenn Sie ein ausgewähltes SET verpassen würden?
quelle
Wenn Sie Dateien haben, die Teil Ihres Produkts werden, muss deren Inhalt korrekt sein. Kein Grund, warum Sie dies nicht bestätigen würden. Wenn Sie beispielsweise in einem Ordner sechs 1024x1024-Bilder benötigen, schreiben Sie auf jeden Fall einen Komponententest, der überprüft, ob Sie genau das haben.
Aber Sie haben wahrscheinlich nicht nur die Dateien, sondern auch Code, der die Dateien liest. Sie könnten einen Komponententest für diesen Code schreiben. Im obigen Beispiel gibt die Funktion zum Lesen eines der sechs Bilder ein 1024 x 1024-Bild im Speicher zurück (oder was auch immer es erzeugen sollte).
Wie auch immer, es ist vielleicht kein Komponententest, aber es ist ein nützlicher Test. Und wenn Sie ein Unit-Test-Framework verwenden, mit dem Sie einen nützlichen Test durchführen können (das ist kein Unit-Test), warum nicht das Unit-Test-Framework verwenden?
quelle
Vielleicht verstehe ich Ihr Problem falsch, aber für mich klingt dies nach einem Problem, das nicht durch einen speziellen Test erfasst werden muss, sondern nur durch das Versionskontrollsystem . Jede Änderung an einer Codebasis sollte vor dem Festschreiben Patch für Patch überprüft werden. Eine einfache Möglichkeit, dies in git zu tun, besteht darin, die Änderungen mit hinzuzufügen
Dabei werden Sie bei jeder Änderung in einer Textdatei vom Arbeitsverzeichnis gefragt, ob Sie diese wirklich behalten möchten. Auf diese Weise können Sie beispielsweise die Löschung dieser „ursprünglichen
SET
Aussagen“ sehen.Falls sich die Codierung einer gesamten Datei ändert, würde jedoch etwas anderes passieren: Der Algorithmus würde alte und neue Datei nicht unterscheiden und daher
git add -p
überhaupt nichts hinzufügen. Dies würde dann in dem anderen Befehl sichtbar sein, den ich vor einem Commit ausführen würde, nämlichHier würden Sie die Datei in rot markiert sehen, was darauf hinweist , dass es sind Änderungen. Die Untersuchung, warum dies nicht gelang,
git add -p
würde das Problem schnell offensichtlich machen.quelle
git
ist das beste Beispiel dafür - ein großartiges Werkzeug, das jedoch für Sterbliche kaum unbrauchbar ist .Ein weiterer zu berücksichtigender Aspekt: Da diese beiden Bedingungen für die Ausführung Ihres Programms erforderlich sind, sollten Sie die Logik nicht in die Nähe der Ausführungslogik einbetten. Ich meine: Sie testen das Vorhandensein einer Datei, bevor Sie sie lesen und / oder ihren Inhalt überprüfen, oder? Wie ist das anders? Ich denke, da dies eine Code-externe Ressource ist, sollte sie zur Laufzeit überprüft werden, bevor sie tatsächlich verwendet wird. Ergebnis: Stärkere App, keine zusätzlichen Tests erforderlich.
quelle
Tests sind derselbe Code wie alle anderen und, wenn sie komplex genug sind, profitieren Sie auch von ... Unit-Tests. Scheint am einfachsten, solche Voraussetzungsprüfungen direkt in den Test aufzunehmen.
Die meisten Tests sind einfach genug, um dies nicht zu erfordern, aber wenn einige komplex genug sind, sehe ich bei diesen Voraussetzungsprüfungen nichts grundsätzlich Falsches. Natürlich sollte der Test auch ohne sie fehlschlagen, aber ein guter Unit-Test zeigt auch an, welche Unit ausfällt .
Ein Skript, das als Teil des Tests verwendet wird und bestimmte Inhalte und Codierungen haben muss, ist wahrscheinlich eine Einheit. Es enthält möglicherweise viel mehr Code und Logik als der Rest des Tests. Ein Test mit einem solchen Skript ist nicht das beste Design aller Zeiten und sollte nach Möglichkeit direkter überarbeitet werden (es sei denn, es handelt sich um einen Integrationstest).
quelle
Erstens - einer der Testzwecke besteht darin, zu verhindern, dass sich Probleme in Ihrem Code wiederholen - sollten Sie unbedingt weiterhin Tests dieser Art schreiben.
Zweitens ist die Benennung schwierig. Ja, dies sind eindeutig keine "Komponententests", aber sie können wünschenswerte und notwendige Teile des Erstellungsprozesses sein, weil sie Sie vor offensichtlichen Fehlern schützen und Sie früher über Fehler informieren (insbesondere, wenn Sie die nicht sehen) Folgen für eine Dev-Box).
Die Frage ist (sollte in Ihrem Kontext stehen), wann und wie diese Tests durchgeführt werden.
Ich habe diese Art von Test in der Vergangenheit ausgiebig genutzt - sie haben uns ein gutes Stück Schmerz erspart.
quelle
Bei Komponententests wird eine Codeeinheit isoliert ausgeführt, um zu bestätigen, dass sie das richtige Ergebnis für die richtige Eingabe liefert. Die Isolierung sollte sowohl den Prüfling als auch den Test selbst wiederholbar machen, dh nicht von Nebenwirkungen abhängen oder diese hervorrufen.
SQL ist nicht genau etwas, das isoliert getestet werden kann. Daher ist jeder SQL-Test nicht genau ein Komponententest und hat mit Ausnahme von SELECT-Anweisungen mit ziemlicher Sicherheit Nebenwirkungen. Wir können es eher einen Integrationstest als einen Komponententest nennen.
Es ist immer ratsam, sicherzustellen, dass ein eventuell auftretender Fehler so früh wie möglich im Entwicklungszyklus erkannt werden kann, und dies auf eine Weise, die es einfach macht, die Fehlerquelle zu identifizieren, damit er schnell gefunden werden kann korrigiert.
Die fraglichen Tests können geeigneterweise aus dem Hauptteil der "Einheitentests" ausgelagert und an einer anderen Stelle platziert werden, sollten jedoch nicht vollständig entfernt werden, wenn sie etwas Nützliches tun, wie das Schützen vor der möglichen Einführung eines Fehlers, dessen Verfolgung Stunden dauern kann Nieder.
quelle