[PYTHON] Berühre den Schein und den Stummel

Überblick

In diesem Satz

erklären. In Python3 ist MagicMock im Standardmodul unittest.mock enthalten. In Python2 können Sie es verwenden, indem Sie das Mock-Paket mit "pip install mock" installieren.

Spielen Sie mit MagicMock

Starten Sie den Python-Interpreter und erstellen Sie ein MagicMock-Objekt

$ python3.6
Python 3.6.0 (default, Feb 27 2017, 00:03:01)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from unittest.mock import MagicMock
>>> f = MagicMock()

Ich gehe davon aus, dass dieses f eine Funktion ist und versuche es aufzurufen

>>> f(1)
<MagicMock name='mock()' id='4381867704'>

Ich kann es aufrufen, obwohl ich es nicht als Funktion definiert habe. Das ist seltsam. Der Rückgabewert ist ebenfalls MagicMock, aber das interessiert mich nicht und ich werde es weiter aufrufen

>>> f(2)
<MagicMock name='mock()' id='4381867704'>
>>> f(1, 2, 3)
<MagicMock name='mock()' id='4381867704'>

Ich könnte es frei nennen, selbst wenn ich den Wert des Arguments und die Anzahl der Argumente ändern würde. Ich bin überrascht. Wenn Sie versuchen, f.call_args_list hier auszuwerten,

>>> f.call_args_list
[call(1), call(2), call(1, 2, 3)]

Ich habe es dreimal aufgerufen, seit ich MagicMock erstellt habe. Sie können sehen, dass es mit den Argumenten aufgezeichnet wird. Es ist interessant.

Dies ist nicht die einzige Funktion von MagicMock. Lassen Sie uns erneut eine MagicMock-Instanz erstellen, den Wert auf "f.return_value" setzen und dann "f" aufrufen.

>>> f = MagicMock()
>>> f.return_value = 5
>>> f(1, 2)
5
>>> f(1)
5
>>> f()
5

Unabhängig davon, welches Argument Sie angeben, wird der festgelegte Wert zurückgegeben. Auf diese Weise können Sie den Rückgabewert der Funktion durch einen beliebigen Wert ersetzen. Auch in diesem Fall wird aufgezeichnet, wie der Anruf getätigt wurde.

>>> f.call_args_list
[call(1, 2), call(1), call()]

Es gibt noch andere Funktionen, aber lassen wir dies zunächst weg und sehen, wie sie helfen können.

Anrufliste

def push():
    pass

def push_if_even(x):
    """()"""
    if x % 2 == 0:
        push()
from unittest.mock import MagicMock

push = MagicMock()
push_if_even(1)
assert len(push.call_args_list) == 0

push = MagicMock()
push_if_even(0)
assert len(push.call_args_list) == 1

print("success")

Insbesondere lautet der Code wie folgt. Nehmen Sie eine Ganzzahl und rufen Sie push auf, wenn es gerade ist. Angenommen, Sie möchten einen Test schreiben, um festzustellen, ob dieser Code korrekt implementiert ist. Wie wir bereits gesehen haben, zeichnet MagicMock auf, was als Funktion bezeichnet wurde, und nutzen dies aus. Sie können es folgendermaßen testen: Sie können auch wie folgt schreiben

push = MagicMock()
push_if_even(1)
push.asset_not_called()

push = MagicMock()
push_if_even(0)
push.assert_called_once()

Werfen wir einen Blick darauf, was passiert, wenn die Bestätigung fehlschlägt.

>>> from unittest.mock import MagicMock
>>> push = MagicMock()
>>> push.assert_called_once()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 795, in assert_called_once
    raise AssertionError(msg)
AssertionError: Expected 'mock' to have been called once. Called 0 times.
>>> push()
<MagicMock name='mock()' id='4356157392'>
>>> push.assert_not_called()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 777, in assert_not_called
    raise AssertionError(msg)
AssertionError: Expected 'mock' to not have been called. Called 1 times.

Rückgabewertsteuerung

Eine Funktion, die True zurückgibt, wenn heute Sonntag ist, False andernfalls "is_sunday"

from datetime import date

def today():
    return date.today()

def is_sunday():
    return today().weekday() == 6

Angenommen, Sie möchten testen, ob dies ordnungsgemäß funktioniert. Wenn heute nicht Sonntag ist, können Sie es einmal aufrufen und sehen, dass es False zurückgibt. Warten Sie dann auf den nächsten Sonntag und rufen Sie es erneut auf, um zu sehen, dass es True zurückgibt. Es wird jedoch Tage dauern, bis der Test abgeschlossen ist. Wenn Sie nicht darauf warten können, können Sie mit MagicMock den Rückgabewert steuern.

from unittest.mock import MagicMock

today = MagicMock()
today.return_value = date(2020, 2, 1)
assert is_sunday() == False

today = MagicMock()
today.return_value = date(2020, 2, 2)
assert is_sunday() == True

print("success")

Wenn ja, können Sie es sofort testen. Es ist bequem.

Zusammenfassung

Nachdem Sie die Natur von MagicMock gesehen haben,

Ich habe den Testcode mithilfe der Funktion von implementiert. Das Testen auf Funktionen, die sich auf die Umgebung auswirken oder von dieser beeinflusst werden, ist schwieriger zu schreiben als das Testen einfacher Funktionen. Sie können jedoch die Auswirkungen auf die Umgebung verspotten oder die Auswirkungen auf die Umgebung unterdrücken. Wir haben gesehen, dass es einfach ist, reproduzierbaren Testcode durch Ersetzen zu erstellen.

In diesem Beispiel habe ich die Funktion einfach überschrieben, aber das Mock-Modul verfügt über eine praktische Funktion namens Patch, mit der die Funktion nur während des Tests ersetzt und anschließend wiederhergestellt werden kann. Verwenden Sie es beim Schreiben von Tests.

Recommended Posts

Berühre den Schein und den Stummel
Mock urllib2 und unittest
Ich werde die Klasse erben und überschreiben
Die Geschichte von Python und die Geschichte von NaN
Führen Sie Pylint aus und lesen Sie die Ergebnisse
Installieren und Deinstallieren der Eierpackung
Berühren Sie das Objekt des neuronalen Netzes
Beurteilen Sie die Erweiterung und laden Sie das Bild herunter
Verständnis und Implementierung des Tonelli-Shanks-Algorithmus (1)
Die Geschichte einer Soundkamera mit Touch Designer und ReSpeaker