Ihr Testschema könnte in etwa so aussehen.
Zuerst schlage ich vor, eine Vorrichtung zu erstellen, die in Ihren verschiedenen Methodentests verwendet werden kann. Das Fixture richtet eine Instanz Ihrer Klasse ein, die in Ihren Tests verwendet werden soll, anstatt die Instanz im Test selbst zu erstellen. Durch die Trennung von Aufgaben auf diese Weise können Sie Ihre Tests robuster und leichter lesbar machen.
from my_package import MyClass
import pytest
@pytest.fixture
def a_test_object():
return MyClass()
Sie können das Testobjekt zu Ihrer Reihe von Verfahren Prüfungen bestehen:
def test_something(a_test_object):
# do the test
Allerdings, wenn Ihr Prüfobjekt einiger Ressourcen während der Installation erfordert (wie zum Beispiel eine Verbindung, eine Datenbank, eine Datei, usw. usw.), können Sie es stattdessen vortäuschen, um die Einrichtung der Ressourcen für den Test zu vermeiden. Eine nützliche Information dazu finden Sie unter this talk.
Übrigens: Wenn Sie mehrere verschiedene Zustände des benutzerdefinierten Objekts, das in Ihrem Gerät erstellt wird, testen müssen, müssen Sie Ihr Gerät parametrieren. Dies ist ein etwas kompliziertes Thema, aber die Dokumentation explains fixture parametrization very clearly.
Die andere Sache, die Sie tun müssen, ist sicherzustellen, dass alle .get
Anrufe an Requests
abgefangen werden. Dies ist wichtig, da es ermöglicht, dass Ihre Tests ohne Internetverbindung ausgeführt werden, und stellt sicher, dass sie nicht als Ergebnis einer fehlerhaften Verbindung ausfallen. Dies ist nicht das, was Sie testen möchten.
Sie können Requests.get
mit dem monkeypatch feature von pytest
abfangen. Alles, was erforderlich ist, ist, monkeypatch
als einen Eingabeparameter für die Testregimenfunktionen aufzunehmen.
Sie können eine andere Vorrichtung verwenden, um dies zu erreichen. Es könnte wie folgt aussehen:
import Requests
import pytest
@pytest.fixture
def patched_requests(monkeypatch):
# store a reference to the old get method
old_get = Requests.get
def mocked_get(uri, *args, **kwargs):
'''A method replacing Requests.get
Returns either a mocked response object (with json method)
or the default response object if the uri doesn't match
one of those that have been supplied.
'''
_, id = uri.split('/users/', 1)
try:
# attempt to get the correct mocked json method
json = dict(
with_address1 = lambda: {'user': {'address': 123}},
with_address2 = lambda: {'user': {'address': 456}},
no_address = lambda: {'user': {}},
no_user = lambda: {},
)[id]
except KeyError:
# fall back to default behavior
obj = old_get(uri, *args, **kwargs)
else:
# create a mocked requests object
mock = type('MockedReq',(), {})()
# assign mocked json to requests.json
mock.json = json
# assign obj to mock
obj = mock
return obj
# finally, patch Requests.get with patched version
monkeypatch.setattr(Requests, 'get', mocked_get)
Das sieht kompliziert, bis Sie verstehen, was geschieht: wir einfach ein paar verspottet json Objekte gemacht haben (durch Wörterbücher dargestellt) mit vorher festgelegten Benutzer-IDs und Adressen. Die gepatchte Version von Requests.get
gibt einfach ein Objekt vom Typ MockedReq
- mit der entsprechenden abgespeckten Methode .json()
zurück, wenn seine ID angefordert wird.
Beachten Sie, dass Requests
nur in Tests gepatcht werden, die tatsächlich die oben Halterung verwenden, z.B .:
def test_something(patched_requests):
# use patched Requests.get
Jeder Test, der nicht patched_requests
als Eingabeparameter nicht verwendet wird nicht die gepatchte Version verwenden.
Beachten Sie auch, dass Sie innerhalb des Tests selbst monkeypatch Requests
, aber ich schlage vor, es separat zu tun. Wenn Sie andere Teile der Anforderungs-API verwenden, müssen Sie diese möglicherweise ebenfalls anpassen.All diese Dinge getrennt zu halten, wird oft einfacher zu verstehen sein, als wenn man sie in den Test mit einbezieht.
Schreiben Sie Ihre verschiedenen Methodentests als nächstes. Sie benötigen für jeden Aspekt Ihrer Methode einen anderen Test. Mit anderen Worten, Sie schreiben in der Regel einen anderen Test für die Instanz, in der Ihre Methode erfolgreich ist, und eine andere für den Test, wenn sie fehlschlägt.
Zuerst testen wir den Methodenerfolg mit ein paar Testfällen.
@pytest.mark.parametrize('id, result', [
('with_address1', 123),
('with_address2', 456),
])
def test_get_user_info_success(patched_requests, a_test_object, id, result):
address = a_test_object.get_user_info(id)
assert address == result
Als nächstes können wir für die Anhebung der BadId
Ausnahme testen Sie die with pytest.raises
Funktion. Beachten Sie, dass, da eine Ausnahme ausgelöst wird, kein result
Eingangsparameter für die Testfunktion vorhanden ist.
@pytest.mark.parametrize('id', [
'no_address',
'no_user',
])
def test_get_user_info_failure(patched_requests, a_test_object, id):
from my_package import BadId
with pytest.raises(BadId):
address = a_test_object.get_user_info(id)
Wie in meinem Kommentar geschrieben, hier sind auch einige zusätzliche Ressourcen, die Sie mehr über pytest lernen zu helfen:
link
link
auch: für die Nachfrage nach Ressourcen wird als Off-Topic SO, aber hier ist, was ich gelernt habe "Pytest": [link] (https://www.youtube.com/watch?v=l32bsaIDoWk&list=PLeo1K3hjS3utzQYDNRNluzqJqpMXx6hHu) [link] (https://www.youtube.com/watch? v = UPanUFVFfzY) [link] (https://www.youtube.com/watch?v=k99HS HQDsi4). –
Vielen Dank @RickTeachey für das Aufzeigen des Fehlers und der Ressourcen. –