Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby
Code

AntiPatterns-Grundlagen: Rails-Tests

by
Length:LongLanguages:

German (Deutsch) translation by Katharina Nevolina (you can also view the original English article)

Dieser Artikel ist eine Einführung in die fortgeschrittenen Gewässer des Testes von AntiPatterns in Schienen. Wenn Sie ein Neuling in der testgetriebenen Entwicklung sind und einige sehr wertvolle empfohlene Vorgehensweise aufgreifen möchten, wurde dieser Artikel genau für Sie geschrieben.

Themen

  • Let
  • Mystery Guests
  • Obskure Tests
  • Slow Tests
  • Fixtures
  • Brittle Tests
  • Datenattribute

Let

Die let-Hilfsmethode in RSpec wird sehr häufig zum Erstellen von Instanzvariablen verwendet, die zwischen mehreren Tests verfügbar sind. Als eifriger Schüler von TDD-Praktiken haben Sie wahrscheinlich Ihren gerechten Anteil daran geschrieben, aber das Befolgen dieser Praxis kann leicht dazu führen, dass viele mysteriöse Gäste auftauchen - siehe unten -, was definitiv nichts ist, was wir brauchen, um unsere Party zum Absturz zu bringen!

Diese besondere Nebenwirkung von let hat den Ruf erlangt, möglicherweise eine erhöhte Testwartung und eine schlechtere Lesbarkeit in Ihrer gesamten Testsuite zu verursachen. let sicher, dass es verlockend klingt, weil es träge bewertet wird und dabei hilft, das normalerweise fehlerfreie Konzept von DRY and all einzuhalten. Daher scheint es zu gut, nicht regelmäßig zu verwenden. subject des nahen Cousins sollte auch die meiste Zeit vermieden werden.

Es wird schlimmer, wenn Sie anfangen, diese Dinge zu verschachteln. Über die verschachtelten describe-Blöcke verputzte let-Anweisungen sind ein absoluter Favorit. Ich denke, es ist nicht unfair, dies als Rezept zu bezeichnen, um sich schnell aufzuhängen. Ein begrenzterer Umfang ist im Allgemeinen leichter zu verstehen und zu befolgen.

Wir wollen kein Kartenhaus mit semi-globalen let-Fixtures bauen, die das Verständnis verdecken und die Wahrscheinlichkeit erhöhen, verwandte Tests zu brechen. Mit einem solchen Ansatz werden die Chancen, Qualitätscode zu erstellen, gegen uns gestapelt. Das Extrahieren der allgemeinen Objektkonfiguration ist bei Bedarf auch einfacher über einfache alte Ruby-Methoden oder sogar Klassen.

Diese let-Kreatur ist eine weit verbreitete Einrichtung, die häufig erst entschlüsselt werden muss, bevor Sie genau wissen, welche Geschäfte dieses Objekt in Ihren Tests hat. Das Hin- und Hergehen, um zu verstehen, woraus sie genau bestehen und welche Beziehungen sie über Assoziationen haben, kann zeitaufwändig sein.

Die Klarheit dieser Details in Ihrem Testaufbau hilft normalerweise sehr dabei, anderen Entwicklern alles zu sagen, was sie für die Arbeit mit jedem bestimmten Teil Ihrer Testsuite benötigen - vergessen Sie nicht Ihr zukünftiges Selbst! In einer Welt, in der Sie niemals bestimmte Tests erneut durchführen und sogar niemals Teile Ihrer Testsuite umgestalten müssen, ist dies möglicherweise nicht so wichtig - aber das ist vorerst ein Wunschtraum!

Wir möchten für jeden Test so wenig Mitarbeiter und so wenig Daten wie möglich haben. let auch an dieser Front gegen dich arbeiten. Diese let-Fixtures können viele Attribute und Methoden anhäufen, die sie auch viel zu groß machen.

Wenn Sie die Straße entlang gehen, werden Sie oft mit ziemlich fetten Gegenständen enden, die versuchen, viele Tests gleichzeitig glücklich zu machen. Sicher, Sie können viele Variationen dieser let-Dinger erstellen, aber das macht die ganze Idee von ihnen ein bisschen irrelevant, denke ich. Warum nicht noch einen Schritt weiter gehen, es vermeiden, sich zu verlassen, und sich auf Ruby ohne RSpec DSL-Magie verlassen?

Ich bin eher im Lager, auf der Seite des wiederholten Setup-Codes für jeden Test zu stehen, als in meiner Testsuite übermäßig trocken, dunkel oder kryptisch zu sein. Ich würde mich immer um mehr Lesbarkeit bemühen. Die Testmethode sollte die Ursache und Wirkung der beteiligten Teile verdeutlichen. Die Verwendung von Objektkollaborateuren, die möglicherweise weit entfernt von Ihrer Testübung definiert sind, liegt nicht in Ihrem Interesse. Wenn Sie Inhalte extrahieren müssen, verwenden Sie ausdrucksstarke Methoden, die dieses Wissen einschließen.

Dies ist so ziemlich immer eine sichere Sache. Auf diese Weise können Sie auch das Setup bereitstellen, das Sie tatsächlich für jeden Test benötigen, und keine Slow Tests verursachen, da unnötige Daten erforderlich sind. Gute alte Variablen, Methoden und Klassen sind oft alles, was Sie brauchen, um schnellere und stabilere Tests bereitzustellen, die einfacher zu lesen sind.

Mystery Guests

Mystery Guests sind wirklich RSpec DSL Puzzles. Für eine Weile sind die verschiedenen Objekte, die über RSpec DSL let definiert wurden, nicht so schwer in Schach zu halten, aber bald, wenn die Testsuite wächst, laden Sie viele mysteriöse Gäste in Ihre Spezifikationen ein. Dies gibt Ihrem zukünftigen Selbst und anderen unnötige Kontext-Rätsel zum Lösen.

Das Ergebnis sind obskure Tests, bei denen Sie in den vollständigen Sherlock Holmes-Modus wechseln müssen. Ich denke, das klingt viel lustiger als es ist. Unterm Strich ist es Zeitverschwendung für alle.

Mystery Guests stellen zwei problematische Fragen:

  • Woher kommt dieses Objekt?
  • Woraus besteht es genau?

Diesem Beschreibungsblock für #top_agent mangelt es an Klarheit und Kontext. Um welchen Agenten handelt es sich und um welche Mission sprechen wir hier? Dies zwingt Entwickler dazu, nach Objekten zu suchen, die plötzlich in Ihren Tests auftauchen.

Klassisches Beispiel Mystery Guests. Wenn zwischen dem relevanten Test und dem Ursprung dieser Objekte viel Code vorhanden ist, erhöhen Sie die Wahrscheinlichkeit, dass die Vorgänge in unseren Tests verdeckt werden.

Die Lösung ist ganz einfach: Sie benötigen neue „Fixtures“ und erstellen lokale Versionen der Objekte mit genau den Daten, die Sie benötigen - und nicht mehr! Factory Girl ist eine gute Wahl, um damit umzugehen.

Dieser Ansatz kann als ausführlicher angesehen werden, und manchmal duplizieren Sie möglicherweise Inhalte - das Extrahieren von Inhalten in eine Methode ist oft eine gute Idee -, aber er ist viel aussagekräftiger und hält die Tests fokussiert, während der Kontext bereitgestellt wird.

Das obige Beispiel erstellt alle Objekte, die für unsere Tests im tatsächlichen Testfall benötigt werden, und bietet den gesamten gewünschten Kontext. Der Entwickler kann sich auf einen bestimmten Testfall konzentrieren und muss keinen weiteren - möglicherweise völlig unabhängigen - Testfall herunterladen, um mit der jeweiligen Situation fertig zu werden. Keine Dunkelheit mehr!

Ja, Sie haben Recht, dieser Ansatz bedeutet, dass wir nicht den niedrigstmöglichen Grad an Duplizierung erreichen. In diesen Fällen ist jedoch die Klarheit für die Qualität Ihrer Testsuite und damit für die Robustheit Ihres Projekts viel wichtiger. In diesem Zusammenhang spielt auch die Geschwindigkeit eine Rolle, mit der Sie Änderungen effektiv auf Ihre Tests anwenden können.

Ein weiterer wichtiger Aspekt beim Testen ist, dass Ihre Testsuite nicht nur als Dokumentation fungieren kann, sondern unbedingt sollte! Null Duplizierung ist kein Ziel, das sich positiv auf die Spezifikationen auswirkt, die Ihre App dokumentieren. Unnötige Doppelarbeit in Schach zu halten, ist dennoch ein wichtiges Ziel - das Gleichgewicht ist hier König!

Obscure Tests

Im Folgenden finden Sie ein weiteres Beispiel, das versucht, alles, was Sie benötigen, lokal im Test einzurichten, aber auch fehlschlägt, weil es uns nicht die ganze Geschichte erzählt.

Wir erstellen einen generischen Agenten. Woher wissen wir, dass es 007 ist? Wir testen auch den Status des Agenten, aber er ist auch nirgends zu finden - weder im Setup noch explizit während der Überprüfungsphase in unserer expect-Anweisung. Die Beziehung zwischen dem double_o_seven.status und dem Missionsstatus könnte verwirrend sein, da er wirklich aus dem Nichts kommt. Wir können es besser machen:

Auch hier haben wir alles, was wir brauchen, um eine Geschichte zu erzählen. Alle Daten, die wir brauchen, liegen direkt vor uns.

Slow Tests

Sie haben also begonnen, sich mit testgetriebener Entwicklung zu befassen, und Sie haben begonnen, das Angebot zu schätzen. Kudos, das ist großartig! Ich bin mir sicher, dass weder die Entscheidung noch die Lernkurve, um dorthin zu gelangen, genau ein Kinderspiel waren. Was jedoch nach diesem ersten Schritt häufig passiert, ist, dass Sie sich bemühen, eine vollständige Testabdeckung zu erreichen, und Sie beginnen zu erkennen, dass etwas nicht stimmt, wenn die Geschwindigkeit Ihrer Spezifikationen Sie zu ärgern beginnt.

Warum wird Ihre Testsuite immer langsamer, obwohl Sie denken, dass Sie die richtigen Dinge tun? Fühlen Sie sich ein bisschen bestraft, wenn Sie Tests schreiben? Slow Tests saugen - große Zeit! Es gibt ein paar Probleme mit ihnen. Das wichtigste Problem ist, dass Slow Tests langfristig zum Überspringen von Tests führen. Sobald Sie an einem Punkt angelangt sind, an dem Ihre Testsuite ewig dauert, werden Sie viel eher bereit sein, sich zu denken: "Scheiß drauf, ich werde sie später ausführen!" Ich habe bessere Dinge zu tun, als darauf zu warten, dass dieses Zeug fertig ist. “ Und Sie haben absolut Recht, Sie haben bessere Dinge zu tun.

Die Sache ist, dass Slow Tests eher zu Kompromissen bei der Qualität Ihres Codes führen, als dies zunächst offensichtlich sein mag. Slow Tests befeuern auch die Argumente der Menschen gegen TDD - zu Unrecht, denke ich. Ich möchte nicht einmal wissen, was nicht-technische Produktmanager zu sagen haben, wenn Sie regelmäßig für eine schöne lange Kaffeepause nach draußen gehen müssen, um Ihre Testsuite auszuführen, bevor Sie Ihre Arbeit fortsetzen können.

Lassen Sie uns diesen Weg nicht gehen! Wenn Sie nur wenig Zeit benötigen, um Ihre Tests durchzuführen, und dadurch superschnelle Feedback-Zyklen für die Entwicklung jedes Schritts neuer Funktionen erhalten, wird das Üben von TDD viel attraktiver und weniger ein Argument. Mit ein wenig Arbeit und Sorgfalt können wir Zeitlupentests sehr effektiv vermeiden.

Slow Tests sind auch ein Killer, um in die „Zone“ zu gelangen. Wenn Sie in Ihrem Prozess so häufig aus dem Fluss genommen werden, kann die Qualität Ihrer gesamten Arbeit auch dadurch beeinträchtigt werden, dass Sie auf Slow Tests warten müssen, um von einer teuren Rundreise zurückzukehren. Sie möchten so viel Zeit wie möglich in der Zone haben - unerträglich Slow Tests sind die Hauptflusskiller.

Ein weiteres erwähnenswertes Problem in diesem Zusammenhang ist, dass dies möglicherweise zu Tests führt, die Ihren Code abdecken. Da Sie sich jedoch nicht die Zeit nehmen, die gesamte Suite zu trainieren oder Tests nachträglich zu schreiben, wird das Design Ihrer Apps nicht so sein mehr von Tests gefahren. Wenn Sie nicht im testgetriebenen Hype-Zug sind, stört Sie das vielleicht nicht sonderlich, aber für TDD-Leute ist dieser Aspekt wichtig und sollte nicht vernachlässigt werden.

Endeffekt: Je schneller Ihre Tests sind, desto mehr sind Sie bereit, sie durchzuführen. Dies ist der beste Weg, um Apps zu entwerfen und Fehler frühzeitig und häufig zu erkennen.

Was können wir tun, um Tests zu beschleunigen? Hier sind zwei Geschwindigkeiten wichtig:

  • Die Geschwindigkeit, mit der Ihre Tests Ihre Suite wirklich ausführen können
  • Die Geschwindigkeit, mit der Sie Feedback von Ihrer Testsuite erhalten, um Ihre App zu entwerfen

Vermeiden Sie es, so viel wie möglich in die Datenbank zu schreiben

Das bedeutet nicht, dass Sie alle Kosten vermeiden sollten. Oft müssen Sie keine Tests schreiben, die die Datenbank trainieren, und Sie könnn viel Zeit sparen, die Ihre Tests zum Ausführen benötigen. Für Test-Setups ist es oft ausreichend, nur new zu verwenden, um ein Objekt zu instanziieren. Das Ausfälschen von Objekten, die nicht direkt getestet werden, ist eine weitere praktikable Option.

Das Erstellen von Test-Doubles ist eine gute Möglichkeit, Ihre Tests zu beschleunigen und gleichzeitig die für Ihr Setup erforderlichen zusammenarbeitenden Objekte super fokussiert und leicht zu halten. Factory Girl bietet Ihnen auch verschiedene Optionen, um Ihre Testdaten intelligent zu "erstellen". Aber manchmal führt kein Weg daran vorbei, in der Datenbank zu speichern (was viel seltener ist als erwartet), und genau hier sollten Sie die Grenze ziehen. Vermeiden Sie es zu jeder anderen Zeit höllisch und Ihre Tetsuite bleibt schnell und agil.

In dieser Hinsicht sollten Sie auch eine minimale Anzahl von Abhängigkeiten anstreben, dh die minimale Anzahl von Objekten, die Sie zusammenarbeiten müssen, um Ihre Tests zu bestehen - und dabei so wenig wie möglich in der Datenbank speichern. Das Stubben von Objekten, die lediglich Mitarbeiter sind und nicht direkt getestet werden, erleichtert häufig auch die Verdauung und das Erstellen Ihres Setups. Ein schöner Geschwindigkeitsschub insgesamt mit sehr wenig Aufwand.

Erstellen Sie Ihre Tests unter Berücksichtigung der Testpyramide

Dies bedeutet, dass Sie die Mehrheit der Komponententests am Ende dieser Hierarchie haben möchten - die sich alle isoliert auf ganz bestimmte Teile Ihrer Anwendung konzentrieren - und die geringste Anzahl von Integrationstests am oberen Rand dieser Pyramide. Integrationstests simulieren einen Benutzer, der Ihr System durchläuft, während er mit einer Reihe von Komponenten interagiert, die ungefähr zur gleichen Zeit ausgeführt werden.

Sie sind leicht zu schreiben, aber nicht so leicht zu warten - und die Geschwindigkeitsverluste sind es nicht wert, den einfachen Weg zu gehen. Integrationstests sind so ziemlich das Gegenteil von Komponententests, da sie ein hohes Niveau aufweisen und viele Komponenten ansaugen, die Sie in Ihren Tests einrichten müssen. Dies ist ein Hauptgrund, warum sie langsamer als Komponententests sind.

Ich denke, dies macht deutlich, warum sie sich an der Spitze Ihrer Testpyramide befinden sollten, um erhebliche Geschwindigkeitsverluste zu vermeiden. Ein weiteres wichtiges Problem ist, dass Sie diese beiden Testkategorien so wenig wie möglich überlappen möchten - idealerweise möchten Sie die Dinge schließlich nur einmal testen. Sie können keine perfekte Trennung erwarten, aber so wenig wie möglich anzustreben ist ein vernünftiges und erreichbares Ziel.

Im Gegensatz zu Unit-Tests möchten Sie mit Integrationstests so wenig Details wie möglich testen. Die innere Mechanik sollte bereits durch umfangreiche Unit-Tests abgedeckt sein. Konzentrieren Sie sich stattdessen nur auf die wichtigsten Teile, die die Interaktionen ausüben müssen! Der andere Hauptgrund ist, dass ein Web-Treiber das Durchsuchen eines Browsers und die Interaktion mit einer Seite simulieren muss. Dieser Ansatz fälscht nichts oder nur sehr wenig aus, speichert das Material in der Datenbank und geht wirklich die Benutzeroberfläche durch.

Dies ist auch ein Grund, warum sie als Abnahmetests bezeichnet werden können, da diese Tests versuchen, eine echte Benutzererfahrung zu simulieren. Dies ist ein weiterer wichtiger Geschwindigkeitsschub, den Sie so wenig wie möglich trainieren möchten. Wenn Sie eine Tonne dieser Tests haben - ich schätze, mehr als 10% Ihrer Gesamtzahl an Tests -, sollten Sie diese Anzahl verlangsamen und auf das Minimum reduzieren.

Denken Sie auch daran, dass Sie manchmal nicht die gesamte App trainieren müssen - oft reicht auch ein kleinerer, fokussierter Ansichtstest aus. Sie werden viel schneller sein, wenn Sie einige Ihrer Integrationstests neu schreiben, die nur ein wenig Logik testen, für die keine vollständige Integrationsprüfung erforderlich ist. Aber schreiben Sie auch nicht eine Tonne davon. Sie bieten den geringsten Knall für das Geld. Abgesehen davon sind Integrationstests für die Qualität Ihrer Testsuite von entscheidender Bedeutung, und Sie müssen ein Gleichgewicht zwischen zu geiziger Anwendung und nicht zu vielen Tests finden.

Erhalten Sie schnell Feedback von Ihrer App und testen Sie

Schnelles Feedback und schnelle Iterationszyklen sind der Schlüssel zum Entwerfen Ihrer Objekte. Sobald Sie vermeiden, diese Tests häufig auszuführen, verlieren Sie diesen Vorteil - eine große Hilfe beim Entwerfen von Objekten. Warten Sie nicht, bis Ihr bevorzugter Continuous Integration-Service aktiviert wird, um Ihre gesamte Anwendung zu testen.

Was ist also eine magische Zahl, die wir bei der Durchführung von Tests berücksichtigen sollten? Nun, verschiedene Leute werden Ihnen verschiedene Benchmarks dafür nennen. Ich denke, dass ein Aufenthalt unter 30 Sekunden eine sehr vernünftige Zahl ist, die es sehr wahrscheinlich macht, regelmäßig einen vollständigen Test durchzuführen. Wenn Sie diesen Benchmark immer mehr hinter sich lassen, ist möglicherweise ein Refactoring angebracht. Es wird sich lohnen und Sie werden sich viel wohler fühlen, weil Sie regelmäßiger einchecken können. Sie werden höchstwahrscheinlich auch viel schneller vorankommen.

Sie möchten, dass dieser Dialog mit Ihren Tests so schnell wie möglich ist. Die Verkürzung dieses Feedback-Zyklus mit einem Editor, der auch Ihre Tests durchführen kann, ist nicht zu unterschätzen. Das Hin- und Herwechseln zwischen Ihrem Editor und Ihrem Terminal ist nicht die beste Lösung, um dies zu handhaben. Das wird sehr schnell alt.

Wenn Sie Vim gerne verwenden, haben Sie noch einen Grund, etwas Zeit in die effizientere Verwendung Ihres Editors zu investieren. Für Vim-Peeps stehen viele praktische Werkzeugs zur Verfügung. Ich erinnere mich, dass Sublime Text auch das Ausführen von Tests innerhalb des Editors anbietet, aber ansonsten müssen Sie ein wenig recherchieren, um herauszufinden, wozu Ihr bevorzugter Editor in dieser Hinsicht in der Lage ist. Das Argument, das Sie häufig von TDD-Enthusiasten hören, ist, dass Sie Ihren Editor nicht verlassen möchten, da Sie insgesamt zu viel Zeit damit verbringen werden. Sie möchten viel mehr in der Zone bleiben und nicht den Gedankengang verlieren, wenn Sie so etwas über eine schnelle Verknüpfung in Ihrem Code-Editor tun können.

Beachten Sie außerdem, dass Sie auch die Tests, die Sie ausführen möchten, in Scheiben schneiden möchten. Wenn Sie nicht die gesamte Datei ausführen müssen, ist es hilfreich, einen einzelnen Test oder einen Block auszuführen, der sich nur auf das konzentriert, was Sie benötigen, um Feedback zu erhalten. Mit Verknüpfungen, mit denen Sie einzelne Tests, einzeln Dateien oder nur den letzten Test erneut ausführen können, sparen Sie eine Menge Zeit und bleiben in der Zone - ganz zu schweigen von dem hohen Maß an Komfort und dem Gefühl, super cool zu sein. Es ist einfach erstaunlich, wie großartig Codierungswerkzeuge manchmal sein können.

Eine letzte Sache für die Straße. Verwenden Sie einen Preloader wie Spring. Sie werden überrascht sein, wie viel Zeit Sie sparen können, wenn Sie Rails nicht für jeden Testlauf laden müssen. Ihre App wird im Hintergrund ausgeführt und muss nicht ständig gestartet werden. Tun Sie es!

Fixtures

Ich bin mir nicht sicher, ob Fixtures für Neulinge, die nach Ruby/Rails kommen, immer noch ein Problem sind. Falls Sie niemand darüber informiert hat, werde ich versuchen, Sie im Handumdrehen über diese gefürchteten Dinge auf dem Laufenden zu halten.

ActiveRecord-Datenbank-Fixtures sind großartige Beispiele dafür, wie viele Mystery Guests in Ihrer Testsuite enthalten sind. In den frühen Tagen von Rails und Ruby TDD waren YAML-Fixtures der De-facto-Standard zum Einrichten von Testdaten in Ihrer Anwendung. Sie spielten eine wichtige Rolle und trugen dazu bei, die Branche voranzubringen. Heutzutage haben sie allerdings einen ziemlich schlechten Ruf.

YAML Fixtures

Die Hash-ähnliche Struktur sieht sicher handlich und einfach zu bedienen aus. Sie können sogar auf andere Knoten verweisen, wenn Sie Assoziationen aus Ihren Modellen simulieren möchten. Aber hier hört die Musik auf und viele sagen, dass ihr Schmerz beginnt. Für Datensätze, die etwas komplizierter sind, sind YAML-Fixtures schwer zu warten und schwer zu ändern, ohne andere Tests zu beeinflussen. Ich meine, Sie können sie natürlich zum Laufen bringen - schließlich haben Entwickler sie in der Vergangenheit häufig verwendet -, aber Tonnen von Entwicklern werden zustimmen, dass der Preis für die Verwaltung von Fixtures nur ein bisschen geizig ist.

Ein Szenario, das wir unbedingt vermeiden möchten, besteht darin, kleine Details an einem vorhandenen Gerät zu ändern und Tonnen von Tests zum Scheitern zu bringen. Wenn diese fehlgeschlagenen Tests nichts miteinander zu tun haben, ist die Situation noch schlimmer - ein gutes Beispiel dafür, dass Tests zu spröde sind. Um vorhandene Tests vor diesem Szenario zu „schützen“, kann dies auch dazu führen, dass Ihr Geräteset über eine vernünftige Größe hinaus wächst. DRY mit Fixtures ist zu diesem Zeitpunkt höchstwahrscheinlich nicht mehr auf dem Tisch.

Um zu vermeiden, dass Ihre Testdaten bei unvermeidlichen Änderungen beschädigt werden, haben Entwickler gerne neuere Strategien eingeführt, die mehr Flexibilität und dynamisches Verhalten bieten. Hier kam Factory Girl ins Spiel und küsste die YAML-Tage zum Abschied.

Ein weiteres Problem ist die starke Abhängigkeit zwischen dem Test und der .yml-Fixture-Datei. Da die Fixtures in einer separaten .yml-Datei definiert sind, sind Mystery Guests auch ein großer Schmerz, der darauf wartet, Sie zu beißen, weil sie dunkel sind. Habe ich erwähnt, dass Fixtures ohne Validierung in die Testdatenbank importiert werden und sich nicht an den Active Record-Lebenszyklus halten? Ja, das ist auch nicht großartig - aus welchem Blickwinkel Sie es auch betrachten möchten!

Mit Factory Girl können Sie all dies vermeiden, indem Sie Objekte erstellen, die für die Tests inline relevant sind - und zwar nur mit den Daten, die für diesen speziellen Fall benötigt werden. Das Motto lautet: Definieren Sie nur das Nötigste in Ihren Werksdefinitionen und fügen Sie den Rest Test für Test hinzu. Das lokale (in Ihren Tests) Überschreiben von Standardwerten, die in Ihren Fabriken definiert wurden, ist ein viel besserer Ansatz als Tonnen von Einhörnern, die darauf warten, in einer Gerätedatei veraltet zu sein.

Dieser Ansatz ist auch skalierbarer. Factory Girl bietet Ihnen zahlreiche Werkzeugs, mit denen Sie alle benötigten Daten erstellen können - so nuanciert wie Sie möchten -, aber Sie erhalten auch jede Menge Munition, um bei Bedarf trocken zu bleiben. Die Vor- und Nachteile dieser Bibliothek sind meiner Meinung nach gut ausgewogen. Auch der Verzicht auf Validierungen gibt keinen Anlass mehr zur Sorge. Ich denke, die Verwendung des Factory-Musters für Testdaten ist mehr als vernünftig und ein Hauptgrund, warum Factory Girl von der Community so gut aufgenommen wurde.

Komplexität ist ein schnell wachsender Feind, mit dem YAML-Fixtures kaum effektiv umgehen können. In gewisser Weise stelle ich mir Fixtures als let Steroide vor. Sie platzieren sie nicht nur noch weiter entfernt - in einer separaten Datei und allen -, sondern laden möglicherweise auch mehr Fixtures vor, als Sie tatsächlich benötigen. RUHE IN FRIEDEN!

Brittle Tests

Wenn Änderungen in Ihren Spezifikationen zu scheinbar nicht zusammenhängenden Fehlern in anderen Tests führen, suchen Sie wahrscheinlich nach einer Testsuite, die aufgrund der oben genannten Ursachen zerbrechlich geworden ist. Diese oft rätselhaften, von Rätseln heimgesuchten Tests führen leicht zu einem instabilen Kartenhaus.

Wenn für Tests erforderliche Objekte "weit entfernt" vom eigentlichen Testszenario definiert werden, ist es nicht so schwer, die Beziehungen zu übersehen, die diese Objekte zu ihren Tests haben. Wenn Code gelöscht, angepasst oder einfach das betreffende Setup-Objekt versehentlich überschrieben wird - ohne zu wissen, wie dies andere Tests beeinflussen könnte -, sind fehlgeschlagene Tests keine seltene Begegnung. Sie erscheinen leicht als völlig unabhängige Fehler. Ich denke, es ist fair, solche Szenarien in die Kategorie des eng gekoppelten Codes aufzunehmen.

In diesem Szenario haben wir den Status eines Objekts, der in unserem Setup definiert wurde, lokal eindeutig geändert. Der betreffende agent ist jetzt ein CIA-Mitarbeiter und hat einen anderen Namen. mission kommt auch wieder aus dem Nichts. Wirklich böses Zeug.

Es ist keine Überraschung, wenn andere Tests, die möglicherweise auf einer anderen Version des agent basieren, in die Luft jagen. Lassen Sie uns den let-Unsinn los und bauen Sie die Objekte, die wir brauchen, genau dort wieder, wo wir sie testen - natürlich nur mit den Attributen, die wir für den Testfall benötigen.

Es ist wichtig zu verstehen, wie Objekte zusammenhängen - idealerweise mit der minimalen Menge an Setup-Code. Sie möchten andere Entwickler nicht auf eine wilde Gänsejagd schicken, um dieses Zeug herauszufinden, wenn sie über Ihren Code stolpern.

Wenn es sehr schwierig ist, schnell einen Überblick zu bekommen und gestern eine neue Funktion implementiert werden musste, können diese Rätsel nicht mit der höchsten Priorität rechnen. Dies wiederum bedeutet oft, dass neue Dinge zusätzlich zu diesem unklaren Kontext entwickelt werden - was eine spröde Grundlage für die Zukunft ist und auch sehr einladend für Fehler auf der Straße ist. Die Lektion, die Sie hier mitnehmen sollten, besteht darin, Dinge nicht zu überschreiben, wo dies möglich ist.

Datenattribute

Ein letzter nützlicher Tipp zur Vermeidung Brittle Tests ist die Verwendung von Datenattributen in Ihren HTML-Tags. Tun Sie sich selbst einen Gefallen und nutzen Sie sie - Sie können mir später danken. Auf diese Weise können Sie die zu testenden Elemente von den Styling-Informationen entkoppeln, die Ihre Designer ohne Ihre Beteiligung häufig berühren.

Wenn Sie eine Klasse wie class='mission-wrapper' in Ihrem Test hart codieren und ein intelligenter Designer beschließt, diesen schlechten Namen zu ändern, wird Ihr Test unnötig beeinträchtigt. Und der Designer ist natürlich nicht schuld. Wie um alles in der Welt würde sie wissen, dass dies einen Teil Ihrer Testsuite betrifft - zumindest sehr unwahrscheinlich.

Wir erwarten, dass ein HTML-Element auf einer Seite angezeigt und mit einer data-role markiert wird. Designer haben keinen Grund, dies zu berühren, und Sie sind vor Brittle Tests geschützt, die aufgrund von Änderungen auf der Stilseite der Dinge auftreten.

Es ist eine ziemlich effektive und nützliche Strategie, die Sie im Grunde nichts dafür kostet. Das einzige, was notwendig sein könnte, ist ein kurzes Gespräch mit den Designern. Stück Kuchen!

Abschließende Gedanken

Wir möchten vermeiden, Menschen abzulenken, die unsere Tests lesen oder, noch schlimmer, sie verwirren. Das öffnet die Tür für Insekten, kann aber auch teuer sein, weil es wertvolle Zeit und Gehirnleistung kosten kann. Versuchen Sie beim Erstellen Ihrer Tests, die Dinge nicht zu überschreiben - dies trägt nicht zur Schaffung von Klarheit bei. Wahrscheinlicher ist, dass dies zu subtilen, zeitaufwändigen Fehlern führt und den Aspekt der Dokumentation Ihres Codes nicht positiv beeinflusst.

Dies schafft eine unnötige Belastung, die wir vermeiden können. Das Mutieren von Testdaten, die mehr als unbedingt notwendig sind, ist es auch wert, ein bisschen paranoid zu sein. Halte es so einfach wie möglich! Dies hilft Ihnen wirklich zu vermeiden, andere Entwickler oder Ihr zukünftiges Ich auf wilde Gänsejagden zu schicken.

Es gibt noch viel über Dinge zu lernen, die Sie beim Testen vermeiden sollten, aber ich glaube, dies ist ein guter Anfang. Leute, die TDD noch nicht kennen, sollten in der Lage sein, diese wenigen Anti-Muster sofort zu handhaben, bevor sie in fortgeschrittenere Gewässer eintauchen.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.