2017-10-26 8 views
2

Ich möchte die Reihenfolge meiner Tests mit Logik steuern, die sie im laufenden Betrieb neu anordnet, während sie bereits ausgeführt werden.Reihenfolge der Tests dynamisch mit Pytest steuern

Mein Anwendungsfall ist dies: Ich parallelisiere meine Tests mit xdist, und jeder Test verwendet externe Ressourcen aus einem gemeinsamen und begrenzten Pool. Einige Tests verwenden mehr Ressourcen als andere. Wenn also nur ein Bruchteil der Ressourcen verfügbar ist, verfügen einige der Tests über die Ressourcen, die sie ausführen müssen, andere nicht.

Ich möchte die Verwendung der Ressourcen optimieren, also möchte ich dynamisch auswählen, welcher Test als nächstes ausgeführt wird, basierend auf den derzeit verfügbaren Ressourcen. Ich würde eine optimale Reihenfolge während der Sammlungsphase berechnen, aber ich weiß nicht im Voraus, wie lange jeder Test dauert, also kann ich nicht vorhersagen, welche Ressourcen wann verfügbar sein werden.

Ich habe keine Möglichkeit gefunden, dieses Verhalten mit einem Plugin zu implementieren, da die Sammlungsphase von der laufenden Phase zu unterscheiden scheint, und ich kenne keine andere Möglichkeit, die Liste der Tests anders als die zu ändern Sammelhaken.

Ich würde sehr schätzen alle Vorschläge, ob eine Möglichkeit, diese oder eine alternative Idee zu implementieren, die die Ressourcenauslastung optimieren würde. Meine Alternative ist es, meinen eigenen simplen Test zu schreiben, aber ich möchte nicht auf den Rest von pytest verzichten.

Danke!

Antwort

1

Nicht wirklich eine vollständige Antwort auf Ihr Problem, sondern auf Ihre Frage zu Pytest und ein paar Hinweise.

Um die Reihenfolge der Tests in pytest zu ändern (nur pytest, nicht pytest-XDIST), können Sie einfach die Reihenfolge der Testpunkte auf dem Sprung ändern, indem Sie diesen Haken Wrapper:

conftest.py:

import pytest 
import random 

random.seed() 

@pytest.hookimpl(hookwrapper=True) 
def pytest_runtest_protocol(item, nextitem): 
    yield 

    idx = item.session.items.index(item) 
    remaining = item.session.items[idx+1:] 
    random.shuffle(remaining) 
    item.session.items[idx+1:] = remaining 

Es macht keinen Sinn zu ändern, was bereits ausgeführt wurde, sondern nur was bleibt - daher [idx+1:]. In diesem Beispiel mische ich nur die Elemente, aber Sie können mit der Liste der verbleibenden Funktionen tun, was Sie wollen.

Denken Sie daran: Dies kann sich darauf auswirken, wie die Geräte & aufgerüstet werden (die des Bereichs über 'Funktion'). Ursprünglich ordnet pytest die Tests an, damit sie die Geräte auf effizienteste Weise nutzen können. Und speziell das Argument nextitem wird intern verwendet, um zu verfolgen, ob das Fixture beendet werden sollte. Da Sie es jedes Mal effizient ändern, können die Auswirkungen unvorhersehbar sein.


Mit pytest-xdist geht alles ganz anders. Sie müssen auf how pytest-dist distributes the tests across the slaves lesen.

Zuerst sammelt jeder Slave alle die gleichen Tests und genau in der gleichen Reihenfolge. Wenn die Reihenfolge anders ist, wird pytest-xdist fehlschlagen. Sie können sie bei der Sammlung nicht neu anordnen.

Zweitens sendet der Master-Prozess die Testindizes in dieser gesammelten Liste als die nächsten auszuführenden Tests. Die Sammlung muss also die ganze Zeit unverändert bleiben.

Drittens können Sie den pytest_xdist_make_scheduler Haken neu definieren. Es gibt im pytest-xdist selbst. Sie können Ihre eigene Logik der Terminierung der Tests in der Methode schedule() definieren, indem Sie die hinzugefügten/entfernten Knoten und die mit den entsprechenden Methoden gesammelten Tests verwenden.

Viertens wäre das zu einfach. Die .schedule() Methode wird nur in slave_collectionfinish Ereignis vom Slave gesendet. Ich bin traurig, das zu sagen, aber Sie müssen die Slave-Prozesse die ganze Zeit töten und neu starten, um dieses Ereignis auszulösen und die verbleibenden Tests neu zu planen.

Wie Sie sehen können, wird die Implementierung des pytest-xdist sehr komplex sein. Aber ich hoffe, das gibt dir einige Hinweise, wo du hinschauen kannst.

Verwandte Themen