In letzter Zeit musste ich Unit-Tests mit Pytest für ein Python-Modul schreiben. Das Modul enthält eine Klasse, in der andere Klassen innerhalb ihres Konstruktors initialisiert werden.
Wie üblich habe ich eine Vorrichtung für diese Klasse erstellt, um das Schreiben eines Tests für jede Klassenmethode zu vereinfachen. Zu diesem Zeitpunkt stieß ich auf einige Probleme, als ich versuchte, die verschiedenen im Konstruktor initiierten Klassen zu verspotten. Das Verspotten funktionierte nicht und es wurden immer noch Instanzen dieser Klassen erstellt.
Nach einigen Recherchen und der Kombination einiger verschiedener Lösungen, die ich online gefunden habe, möchte ich mitteilen, wie ich es geschafft habe, die Klassen nachzuahmen.
Hier ist ein Beispiel der Klasse, die ich zu verspotten versuchte:
class ClassA: def __init__(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Wir möchten bei Tests für jedes Feld dieser Klasse einen Wert festlegen. Dieser Wert kann None oder ein Klassenmock sein, aber wir wollen keine Initiationen der Klassen ClassB und ClassC.
In unserem Fall entscheiden wir, dass self.class_b und self.class_c Mocks sein sollten:
@pytest.fixture def mock_class_b(): class_b = Mock(spec=ClassB) return class_b @pytest.fixture def mock_class_c(): class_c = Mock(spec=ClassC) return class_c
Ein Spielplan für diese Klasse, der unserem Ziel dient, sieht also so aus:
@pytest.fixture def class_a_mock(mock_class_b, mock_class_c): with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init: class_a = ClassA() class_a.class_b = mock_class_b class_a.class_c = mock_class_c class_b.count = 0 return class_a
Der wichtige Teil ist die Verwendung der Funktion patch.object, die aus dem Modul unittest.mock in Python stammt. Es wird beim Testen verwendet, um ein Attribut eines bestimmten Objekts vorübergehend durch einen Schein oder einen anderen Wert zu ersetzen.
Argumente
Auf diese Weise können wir simulierte Variablen in unserem Fixture erstellen.
Lesen Sie mehr über patch.object
Ich habe dieses Tutorial für solche Fälle geschrieben, in denen wir den Code der Klasse A aus irgendeinem Grund nicht ändern können. Ich empfehle jedoch generell, den Code nach Möglichkeit zu ändern, nicht um die Logik zu ändern, sondern um ihn testbarer zu machen .
Hier sind einige Beispiele, wie man Klasse A ändern kann, um sie testbarer zu machen:
Option 1: Übergeben Sie Instanzen von Klasse B und Klasse C als Parameter.
Auf diese Weise können wir beim Schreiben des Fixtures Mocks anstelle von Instanzen übergeben.
class ClassA: def __init__(self, class_b_instance, class_c_instance): self.class_b = class_b_instance self.class_c = class_c_instance self.count = 0
Option 2: Erstellen Sie eine boolesche Variable, die den Testmodus angibt.
Auf diese Weise können wir entscheiden, welche Felder der Klasse A bei ihrer Initiierung einen Wert erhalten oder nicht.
class ClassA: def __init__(self, test_mode=False): if not test_mode: self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Option 3: Klasseninitialisierungen in einer separaten Methode durchführen.
Dieser Ansatz gibt uns die Möglichkeit, den Aufruf von set_class_variables im Testmodul zu vermeiden.
class ClassA: def __init__(self): self.class_b = None self.class_c = None self.count = None def set_class_variables(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Ich hoffe, das hilft! :)
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3