Hallo. Das ist leo1109. Dieses Mal ist eine Fortsetzung des Artikels (Überprüfung des Codeformats) von vorherige.
Der gesamte im Artikel verwendete Code wurde auf GitHub hochgeladen.
Es geht darum, einen Test zu schreiben. Verwenden Sie Pytest.
Die Pytest-Dokumentation enthält das folgende Beispiel:
inc (x) ist eine Funktion, die den Wert von x plus 1 zurückgibt. (Zuwachs) Als Test wird test_answer () definiert.
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
Führen Sie den Test aus. Sie müssen pytest installieren, führen Sie die Installation entweder mit pip oder aus Bitte installieren Sie mit require.txt im Repository.
pip install pytest
pip install -r requrements.txt
Versuchen Sie, pytest auszuführen.
$ pytest
======= test session starts ========
collected 1 item
test_sample.py F
======= FAILURES ========
_______ test_answer ________
def test_answer():
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = inc(3)
test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========
Da inc (3) 4 zurückgeben soll, ist es nicht gleich 5, daher wurde es als Fehler beurteilt.
Jetzt schreiben wir einen Test.
get_fibonacci_by_index(1)
Gibt 1 zurück, schreiben wir also einen Test, um sicherzustellen, dass 1 zurückgegeben wird.
# python 3.5.2
import my_math
class TestGetFibonacciByIndex:
def test(self):
assert my_math.get_fibonacci_by_index(1) == 1
Das Folgende ist das Ergebnis der Ausführung.
$ pytest my_math_test.py
================================================================================= test session starts =================================================================================
my_math_test.py .
============================================================================== 1 passed in 0.03 seconds ===============================================================================
Im Gegensatz zu zuvor wurde es als 1 bestanden angezeigt.
Lassen Sie uns auch andere Muster testen.
Um einen Testfall hinzuzufügen, können Sie einfach den Assert hinzufügen. Abhängig von der Granularität des Tests müssen Sie möglicherweise sicherstellen, dass der Rückgabewert Int ist.
Da es als Python-Code angewendet wird, können nicht nur verschiedene Operatoren, sondern auch Arrays und Wörterbücher verwendet werden.
# python 3.5.2
import my_math
class TestGetFibonacciByIndex:
def test(self):
assert my_math.get_fibonacci_by_index(1) == 1
assert my_math.get_fibonacci_by_index(2) == 1
assert my_math.get_fibonacci_by_index(3) == 2
assert my_math.get_fibonacci_by_index(4) > 2
assert (my_math.get_fibonacci_by_index(5) == 5) is True
def test_is_instance(self):
assert isinstance(my_math.get_fibonacci_by_index(2), int)
def test_as_array(self):
expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
got = []
for i in range(1, 11):
got.append(my_math.get_fibonacci_by_index(i))
assert expected == got
Lass es uns laufen. Bei Ausführung mit der Option v werden die Ergebnisse für jede Testmethode angezeigt. Der Methodenname muss mit test beginnen, damit der Test ausgeführt werden kann.
$ pytest my_math_test.py -v
================================================================================= test session starts =================================================================================
my_math_test.py::TestGetFibonacciByIndex::test PASSED
my_math_test.py::TestGetFibonacciByIndex::test_is_instance PASSED
my_math_test.py::TestGetFibonacciByIndex::test_as_array PASSED
============================================================================== 3 passed in 0.09 seconds ===============================================================================
Was passiert übrigens, wenn Sie get_fibonacci_by_index (x) eine 0 oder eine negative Zahl geben? Bisher haben Sie nur natürliche Zahlen angegeben.
Wenn ich 0 und -1 gab, bekam ich 1. Ist das das beabsichtigte Verhalten?
>>> import my_math; my_math.get_fibonacci_by_index(0)
1
>>> import my_math; my_math.get_fibonacci_by_index(-1)
1
Wenn man sich den Quellcode ansieht, scheint es, dass er 1 zurückgibt, es sei denn, er geht in den Bereich (1, x).
Es ist wichtig, einen Test für verschiedene Fälle zu schreiben, aber es ist schwierig, zu viel zu erreichen. Was ist zum Beispiel, wenn eine Zeichenfolge als Argument eingeht? Was ist, wenn der Bool-Wert kommt? Etc.
In diesem `get_fibonacci_by_index (x)`
sollte (x) für natürliche Zahlen stehen.
Daher sollte es möglich sein zu definieren, dass nur natürliche Zahlen angenommen werden.
... aber diesmal schreiben wir einen Test! Machen wir also einen kleinen Umweg. Siehe den Testfall unten.
def test_bool(self):
assert my_math.get_fibonacci_by_index(True) == 1
assert my_math.get_fibonacci_by_index(False) == 1
Dieser Test besteht unerwartet.
Der Grund ist, dass `True and False``` als
`Int``` ausgewertet werden kann, was jeweils 1,0 ist.
>>> int(True)
1
>>> int(False)
0
Wenn Sie in Zukunft eine Implementierung hinzufügen, die den Typ streng überprüft, besteht dieser Test möglicherweise nicht.
Der Fall, in dem `` `True, False``` angegeben ist, sollte jedoch nicht das beabsichtigte Muster sein. Schreiben wir daher einen Test, der diesmal "TypeError" erwartet.
pytest.Sie können Tests schreiben, die Ausnahmen erwarten, indem Sie Erhöhungen in Verbindung mit der with-Klausel verwenden.
def test_bool(self):
with pytest.raises(TypeError):
my_math.get_fibonacci_by_index(True)
with pytest.raises(TypeError):
my_math.get_fibonacci_by_index(False)
Aber natürlich besteht der Test nicht.
Es sieht nicht sehr gut aus, es in diesem Zustand zu belassen ...
$ pytest -v my_math_test.py ================================================================================= test session starts =================================================================================
my_math_test.py::TestGetFibonacciByIndex::test PASSED my_math_test.py::TestGetFibonacciByIndex::test_is_instance PASSED my_math_test.py::TestGetFibonacciByIndex::test_as_array PASSED my_math_test.py::TestGetFibonacciByIndex::test_bool FAILED
====================================================================================== FAILURES ======================================================================================= __________________________________________________________________________ TestGetFibonacciByIndex.test_bool __________________________________________________________________________
self = <my_math_test.TestGetFibonacciByIndex object at 0x10566de10>
def test_bool(self):
with pytest.raises(TypeError):
my_math.get_fibonacci_by_index(True)
E Failed: DID NOT RAISE <class 'TypeError'>
my_math_test.py:30: Failed ========================================================================= 1 failed, 3 passed in 0.12 seconds ==========================================================================
Lassen Sie uns diesen Test also einmal überspringen.
## Überspringen Sie den Test
Verwenden wir pytest als Dekorateur.
#### **`pytest.mark.Sie können den Zieltest überspringen, indem Sie überspringen.`**
Fügen Sie dem Import `` `pytest``` hinzu.
import pytest
..
@pytest.mark.skip
def test_bool(self):
with pytest.raises(TypeError):
my_math.get_fibonacci_by_index(True)
with pytest.raises(TypeError):
my_math.get_fibonacci_by_index(False)
Sie können auch die zu überspringenden Bedingungen angeben.
sys.version_info ist eine Redewendung, um die Python-Version zu erhalten.
Vergessen Sie natürlich nicht, sys zu importieren.
import sys .. @pytest.mark.skipif(sys.version_info < (3,5), reason="requires python 3.5") def test_requires_35(self): assert True
Wenn Sie es unter Python 2.7.11 bzw. Python 3.5.2 ausführen, können Sie sehen, dass der Zieltest in 2.7.11 übersprungen wird.
$ pytest -v my_math_test.py ================================================================================= test session starts ================================================================================= platform darwin -- Python 2.7.11, pytest-3.2.0, py-1.4.34, pluggy-0.4.0
my_math_test.py::TestGetFibonacciByIndex::test_requires_35 SKIPPED
$ pytest -v my_math_test.py ================================================================================= test session starts ================================================================================= platform darwin -- Python 3.5.2, pytest-3.2.0, py-1.4.34, pluggy-0.4.0
my_math_test.py::TestGetFibonacciByIndex::test_requires_35 PASSED
Dies ist nützlich, wenn Sie eine Funktion verwenden, die nur in einer bestimmten Version implementiert ist, oder wenn Sie ein Modul implementieren, das mehrere Versionen unterstützt.
Außerdem ist `` `pyenv``` nützlich, wenn Sie zwischen Python-Versionen wechseln, um diese auszuführen.
(Die Erklärung von pyenv unterscheidet sich vom Inhalt dieses Kapitels, daher werde ich sie weglassen.)
- https://github.com/pyenv/pyenv
## Passen Sie die Reihenfolge der Importe an
Wenn Sie den Code wie oben schreiben, sollten die folgenden drei Importe geschrieben werden.
import sys
import pytest
import my_math
Tatsächlich stehen auch Tools zum Anpassen dieser Reihenfolge zur Verfügung.
Sie können isort verwenden, um Importe zu sortieren.
(Es gibt verschiedene andere Funktionen, aber dies ist nur eine kurze Einführung.)
- https://github.com/timothycrosley/isort
Nun, ich konnte den Test sicher schreiben. Es ist sehr leicht!
Wenn Sie Code hinzufügen, können Sie Implementierungsfehler reduzieren, indem Sie sich angewöhnen, Tests zu schreiben.
## nächstes Mal
Ich möchte Tests für komplexe Methoden in Python schreiben! ist.
Recommended Posts