Drei Jahre Autotests: Wie man die Geschwindigkeit erhöht und nicht nur


Hallo, ich bin Alexey, Full-Stack-Entwickler der Vimbox-Plattform. Als ich zu Skyeng kam, entschieden sie hier, ob es sich lohnt, sich mit dem Autotest-System zu beschäftigen, und baten mich, meine Erfahrungen aus der vorherigen Arbeit mitzuteilen. Und ich hatte solche Erfahrungen: Als wir den vorherigen Ort verließen, schrieben wir in PHP und verdrehten mehr als dreitausend Tests. Infolgedessen hielt ich eine kleine interne Präsentation über den Rechen, den ich in einigen Jahren bei der Entwicklung dieser Autotests geschafft hatte, und kämpfte um ihre Geschwindigkeit, Lesbarkeit des Codes und Gesamteffizienz. Die Präsentation schien für Kollegen nützlich zu sein, deshalb habe ich sie in den Text eingefügt, um auch für ein breiteres Publikum nützlich zu sein.


Zunächst die Begriffe, die im Artikel behandelt werden:


  • Abnahmetest - End-to-End-Test: Hier führt der Browser oder Browser-Emulator das Skript aus
  • Unit Test (Unit Test) - Methodentest
  • Funktionstest - Ein Test eines Controllers oder einer Komponente, wenn es um das Frontend geht
  • Fixture - Der Status der Testumgebung, die für die Ausführung des Tests erforderlich ist (globale Variablen, Daten in der Datenbank und andere Teilnehmer am Testskript).

Vor- und Nachteile verschiedener Arten von Tests



Abnahmetests


  • Vorteile: Aus dem Namen ersichtlich, decken solche Tests das gesamte System von oben bis unten ab. Stellen Sie sicher, dass alles so funktioniert, wie es sollte.
  • Nachteile: Die Rückmeldungen zu diesen Tests sind sehr langsam, sie funktionieren lange, sie sind nicht sehr zuverlässig, es gibt viele Fehlalarme. Bei einem früheren Job waren wir auch mit der Tatsache konfrontiert, dass Web-Treiber einige der Elemente, die wir mit unseren Augen sahen, nicht erkannten. Nun wurde dies wahrscheinlich behoben, aber dann musste ich sie aufgeben.

Unit-Tests


  • Vorteile: einfach zu schreiben, schnell arbeiten. Sie decken einen kleinen Teil des Codes ab, Sie benötigen nicht viele Zustände, daher benötigen Sie auch kein großes Gerät.
  • Nachteile: Instabil gegenüber Änderungen in der Architektur oder der internen Struktur des Codes. Wenn Sie zwei Methoden zu einer oder einer separaten zusammenführen müssen, eine Klasse auswählen, eine Methode löschen und die Tests neu schreiben müssen.

Funktionstests sind eine Zwischenlösung.


  • Vorteile: zuverlässigere Akzeptanz, widerstandsfähiger gegen Änderungen in der Struktur des Codes als modular.
  • Nachteile: langsamer als modular, schwieriger zu schreiben, weil müssen ein großes Gerät vorbereiten.

Der Kampf um Geschwindigkeit


Bei der alten Arbeit haben wir viele Funktionstests geschrieben, und die größte Herausforderung war die Reaktionsgeschwindigkeit. Ich musste lange auf das Ergebnis warten, selbst bei einem lokalen Start auf dem Computer des Entwicklers. Die Geschwindigkeit war so langsam, dass es nicht möglich war, den Ansatz „Entwicklung durch Testen“ anzuwenden, da Autotests mehrmals pro Stunde ausgeführt werden. Einen Engpass gefunden - Arbeiten mit der Datenbank. Wie gehe ich damit um?


Erleben Sie zuerst: Moki


Mock in PhpUnit ist ein dynamisch erstelltes Objekt, dessen Klasse dynamisch von der parodierten Klasse geerbt wird. Sie können konfigurieren, welche Methoden des Moks zurückgegeben werden. Sie können überprüfen, welche Methoden des MoQ wie oft mit welchen Parametern aufgerufen wurden


Das Hauptvorteil von Moki - Sie ermöglichen es Ihnen, ganze Funktionen abzuschneiden. Wenn wir den Service durch moch ersetzen, müssen wir nicht mehr darüber nachdenken, was dort passiert, sondern zusätzliche Skripte und Fixtures entwickeln, damit alles richtig funktioniert. Infolgedessen: weniger Fixtures und die Antwortgeschwindigkeit ist höher, da wir den zusätzlichen Code abschneiden, der Abfragen an die Datenbank ausführt.


Das implizite Plus von Mobs ist, dass sie es besser machen, Abhängigkeiten zu organisieren. Wenn Sie einen Code schreiben und wissen, dass ein Test darauf geschrieben werden muss, bei dem etwas durch Mokami ersetzt wird, denken Sie sofort an Abhängigkeiten.


Minus : Der Testcode ist zu stark an die Implementierung angehängt. Während des Tests müssen wir ein Scheinobjekt erstellen und darüber nachdenken, welche Methoden darauf aufgerufen werden sollen.


Das zweite Minus ist, dass die Tests weniger zuverlässig geworden sind. Sie "bemerken" nicht einmal Änderungen in der Schnittstelle, ganz zu schweigen von der Implementierung. Das heißt, Wir haben die Methode irgendwo gelöscht und nach langer Zeit festgestellt, dass die Tests, die sie abdecken, immer noch so funktionieren, als wäre nichts passiert, weil wir ihren Schein gesehen haben, und er tat so, als wäre alles in Ordnung.


Ich halte die Erfahrung mit Mokas für erfolglos, um Tests zu beschleunigen.


Erleben Sie zwei: SQLite


Die nächste Option ist SQLite DBMS . Es kann eine Datenbank im RAM erstellen. Ich musste ein PostgreSQL-Übersetzerschema in SQLite schreiben, nach jeder Migration wurde ein neues SQLite-Schema generiert. Tests von dieser Schaltung erstellten eine leere Datenbank im RAM. Dieser Ansatz erhöhte die Testgeschwindigkeit auf lokalen Maschinen um das Zwei- bis Vierfache. Es wurde realistisch, die gesamte Testsuite mehrmals pro Stunde auszuführen.


Aber es gab Nachteile. Wir haben viele der nativen PostgreSQL-Funktionen verloren (json, einige praktische Aggregatfunktionen und mehr). Abfragen mussten so geschrieben werden, dass sie sowohl mit PostgreSQL als auch mit SQLite funktionieren.


Erleben Sie drei: PostgreSQL-Optimierung


Diese Entscheidung funktionierte, verursachte aber einige Schmerzen. Irgendwann haben wir erfahren, dass PostgreSQL für Autotests optimiert werden kann, wodurch sich die Antwortzeit um etwa das Vierfache verringert. Fügen Sie dazu postgresql.conf einige Einstellungen hinzu:


fsync=off synchronous_commit=off full_page_writes=off 

Dies sind Zuverlässigkeitseinstellungen. Sie garantieren, dass der Server, wenn er während einer Transaktion stirbt, korrekt beendet wird, wenn alles wieder funktioniert. Es ist klar, dass solche Einstellungen nicht in der Produktion vorgenommen werden können, aber es war praktisch bei automatischen Tests.


Diese Einstellung wird auf den gesamten Cluster angewendet, wirkt sich auf alle Datenbanken aus und kann nicht auf eine Datenbank angewendet werden. Wenn Sie es schaffen, die Datenbanken in einem separaten Cluster zu lokalisieren und fsync darin zu deaktivieren, ist dies sehr praktisch.


Ein bisschen über new


Ich möchte auch die Gefahr des new Betreibers erwähnen. Mit seiner Hilfe erstellte Dienste können nicht durch Mokas und Stubs ersetzt werden. Fazit:


  • Verwenden Sie new , um Objekte zu erstellen, die im Wesentlichen Services sind.
  • Es kann in Fabriken eingesetzt werden, da sie ersetzt werden können. Aber Fabriken selbst sollten nicht durch new geschaffen werden.
  • Es kann verwendet werden, um Modelle, Entitäten, DTO (Datenübertragungsobjekt), Wertobjekte zu erstellen.

Schlussfolgerungen aus drei Jahren Erfahrung


  • Bei der vorherigen Arbeit haben wir Abnahmetests abgelehnt, aber jetzt würde ich sie erneut versuchen: Höchstwahrscheinlich wurden viele Fehler in Webtreibern behoben.
  • Wenn Sie neue Funktionen mit Tests abdecken möchten, müssen Sie nur Funktionstests von Steuerungen / Komponenten schreiben. In dieser Situation besteht ein hohes Risiko für strukturelle Veränderungen, Unit-Tests sind für sie instabil.
  • Es sollte nicht viele solcher Tests geben, da viele == langsam nicht so schnell funktionieren wie modulare. Es lohnt sich, nur die Fälle abzudecken, die „schießen“ können (sie haben die Wahrscheinlichkeit eines Fehlers in der Zukunft).
  • Unit-Tests basieren auf algorithmischen Methoden (komplexe Logik, die getestet werden muss) oder auf Methoden mit geringem Risiko für strukturelle Änderungen in der Zukunft.
  • Die Nachteile von Moka übertreffen im Allgemeinen die Vorteile. Es ist sinnvoll, sie nur als Ersatz für Gateways in externe APIs und manchmal für Dienste aus Legacy-Code zu verwenden, die sehr schwer zu testen sind.
  • Wenn Sie Code ohne Test schreiben möchten, sollten Sie sich überlegen: „Wenn Sie ihn erstellen, was ist, wenn wir in Zukunft noch einen Test dafür schreiben möchten?
  • Tests sollten einfach und angenehm zu schreiben sein, sie geben Zuverlässigkeit, Vertrauen, helfen, den Code besser zu verstehen und Abhängigkeiten zu verwalten.
  • Achten Sie auf die Lesbarkeit der Tests. Man muss sich auf den Testcode genauso beziehen wie auf den Code, den er abdeckt.
  • DB-Geräte - Teil des Tests, sollten ebenfalls lesbar sein

Source: https://habr.com/ru/post/de461901/


All Articles