Parallele PHPUnit-Tests in Integrationstests

9

Da die Zeit, die für das Ausführen der PHPUnit-Suite benötigt wird, ansteigt, fragt sich unser Team, ob Tests parallel ausgeführt werden können . Kürzlich habe ich einen Artikel über Paraunit gelesen, auch Sebastian Bergman schrieb, er fügt PHPUnit 3.7 Parallelität hinzu.

Aber es gibt das Problem mit Integrationstests oder allgemeiner Tests, die mit DB interagieren. Aus Konsistenzgründen muss die testDB nach jedem Test zurückgesetzt und Fixtures geladen werden. Aber in parallelen Tests gibt es ein Problem mit Race-Bedingungen, weil alle Prozesse die gleiche DB verwenden .

Um Integrationstests parallel ausführen zu können, müssen wir jedem Prozess eine eigene Datenbank zuweisen . Ich würde gerne fragen, ob jemand darüber nachdenkt, wie dieses Problem gelöst werden kann. Vielleicht gibt es bereits implementierte Lösungen für dieses Problem in einer anderen xUnit-Implementierung.

In meinem Team verwenden wir MongoDB, also wäre eine Lösung programmatisch eine Konfigurationsdatei für jeden PHPUnit-Prozess mit generiertem DB-Namen (für diesen Prozess) zu erstellen, und in setUp() method könnten wir das Haupt-TestDb in klonen dieser temporäre. Bevor wir jedoch mit der Umsetzung dieses Ansatzes beginnen, möchte ich um Ihre Ideen zu dem Thema bitten.

    
gennadi.w 10.06.2013, 08:30
quelle

3 Antworten

4

Das ist eine gute Frage: Vorbereitung für parallele Komponententests erfordert einige neue Best Practices, und ich vermute, einige von ihnen werden unsere Tests verlangsamen.

Auf der obersten Ebene lautet der Rat: Vermeide es, möglichst mit einer Datenbank zu testen. Zeichnen Sie alle Interaktionen mit Ihrer Datenbank ab und spotten Sie dann über diese Klasse. Aber Sie haben bereits bemerkt, dass Ihre Frage Integrationstests betrifft, wo dies nicht möglich ist.

Wenn ich PDO verwende, benutze ich generell sqlite :: memory: Jeder Test bekommt seine eigene Datenbank. Es ist anonym und automatisch bereinigt, wenn der Test endet. (Aber ich bemerkte einige Probleme damit, wenn Ihre reale Anwendung nicht sqlite verwendet: Vorschläge zur Vermeidung von DB-Deps bei Verwendung einer SQL-In-Memory-DB um Unit-Tests zu beschleunigen )

Wenn Sie eine Datenbank verwenden, für die keine speicherinterne Option verfügbar ist, erstellen Sie die Datenbank mit einem zufälligen Namen. Wenn die Parallelisierung auf der PHPUnit-Prozessebene ziemlich grob ist, könnten Sie die Prozess-PID verwenden. Aber das hat keine wirklichen Vorteile gegenüber einem zufälligen Namen. (Ich weiß, PHP ist single-threaded, aber vielleicht würden wir in Zukunft ein benutzerdefiniertes phpUnit-Modul haben, das Threads benutzt, um Tests parallel auszuführen; wir könnten genauso gut dafür bereit sein.)

Wenn Sie das Buch xUnit Test Patterns haben, geht es in Kapitel 13 um das Testen von Datenbanken (relativ kurz). Die Kapitel 8 und 9 über transiente und dauerhafte Fixtures sind ebenfalls hilfreich. Und natürlich ist das meiste des Buches auf Abstraktionsschichten, um das Mocking einfacher zu machen: -)

    
Darren Cook 11.06.2013, 00:22
quelle
0
  

Aber es bleibt das Problem mit Integrationstests oder mehr   im Allgemeinen Tests, die mit DB interagieren. Aus Gründen der Konsistenz   Nach jedem Test muss die Testdatenbank zurückgesetzt und die Fixtures geladen werden. Aber   In parallelen Tests gibt es ein Problem mit den Rennbedingungen, weil alle   Prozesse verwenden den gleichen DB.

     

Um Integrationstests parallel durchführen zu können, müssen wir also zuweisen   eigene Datenbank zu jedem Prozess. Ich würde gerne fragen, ob jemand welche hat   Gedanken darüber, wie dieses Problem gelöst werden kann. Vielleicht sind es schon   implementiert Lösungen für dieses Problem in einer anderen xUnit-Implementierung.

Sie können Integrationstestkonflikte auf zwei Arten vermeiden:

  • führt nur parallele Tests durch, die sehr unterschiedliche Tabellen Ihrer Datenbank verwenden, so dass sie nicht in Konflikt stehen
  • Erstellen Sie eine neue Datenbank für in Konflikt stehende Tests

Ofc. Sie können diese 2 Lösungen kombinieren. Ich weiß nichts über einen phpunit-Test-Runner, der einen dieser Ansätze unterstützt, daher denke ich, dass Sie einen eigenen Test-Runner schreiben müssen, um den Prozess zu beschleunigen ... Übrigens können Sie Ihre Integrationstests noch gruppieren und nur einige wenige ausführen von ihnen sofort, wenn Sie sie durch Entwicklung verwenden ...

Beachten Sie, dass die gleichen Konflikte in PHP zu Problemen bei der Parallelität führen können. Wenn Sie beispielsweise 2 Dateien in umgekehrter Reihenfolge unter 2 separaten Controller-Aktionen sperren, kann Ihre Anwendung in einem Deadlock enden ... Ich suche nach einem Weg, Parallelitätsprobleme in PHP zu testen, aber bisher kein Glück. Ich habe momentan keine Zeit, um meine eigene Lösung zu schreiben, und ich bin mir nicht sicher, ob ich es schaffen kann, es ist ziemlich harte Sachen ...: S

    
inf3rno 07.04.2014 15:50
quelle
0

Es gibt auch diese großartige Bibliothek ( schnellste ), um Tests parallel durchzuführen. Es ist für funktionale / Integrationstests optimiert und bietet eine einfache Möglichkeit, mit N Datenbanken parallel zu arbeiten.

  

Unsere alte Codebase läuft in 30 Minuten, jetzt in 7 Minuten mit 4 Prozessoren.

Funktionen

  • Funktionelle Tests könnten eine Datenbank pro Prozessor mit dem verwenden Umgebungsvariable.
  • Tests werden standardmäßig randomisiert.
  • Ist nicht mit PHPUnit gekoppelt, Sie könnten einen beliebigen Befehl ausführen.
  • Wird in PHP ohne Abhängigkeiten entwickelt.
  • Als Eingabe können Sie eine phpunit.xml.dist-Datei verwenden oder eine Pipe verwenden.
  • Enthält eine Behat-Erweiterung, um Szenarien schnell in die schnellste zu leiten.
  • Erhöhen Sie die Ausführlichkeit mit der Option -v.

Verwendung

find tests/ -name "*Test.php" | ./bin/fastest "bin/phpunit -c app {};"

    
Mohamed Ramrami 31.01.2017 16:29
quelle