Bonjour. C'est leo1109. Cette fois-ci est une suite de l'article (vérification du format de code) de précédent.
Tout le code utilisé dans l'article a été téléchargé sur GitHub.
Il s'agit d'écrire un test. Utilisez pytest.
La documentation de pytest a l'exemple suivant:
inc (x) est une fonction qui renvoie la valeur de x plus 1. (Incrément) En tant que test, test_answer () est défini.
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
Exécutez le test. Vous devez installer pytest, alors exécutez l'installation avec pip ou Veuillez installer en utilisant requirements.txt dans le référentiel.
pip install pytest
pip install -r requrements.txt
Essayez d'exécuter pytest.
$ 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 ========
Puisque inc (3) est censé renvoyer 4, il n'est pas égal à 5, donc il a été jugé comme un échec.
Maintenant, écrivons un test.
get_fibonacci_by_index(1)
Renvoie 1, alors écrivons un test pour nous assurer qu'il renvoie 1.
# python 3.5.2
import my_math
class TestGetFibonacciByIndex:
def test(self):
assert my_math.get_fibonacci_by_index(1) == 1
Ce qui suit est le résultat de l'exécution.
$ pytest my_math_test.py
================================================================================= test session starts =================================================================================
my_math_test.py .
============================================================================== 1 passed in 0.03 seconds ===============================================================================
Contrairement à avant, il était affiché comme 1 réussi.
Testons également d'autres modèles.
Pour ajouter un cas de test, il est facile d'ajouter l'assert tel quel. En fonction de la granularité du test, vous devrez peut-être vous assurer que la valeur de retour est Int.
Puisqu'il est appliqué en tant que code Python, non seulement divers opérateurs mais également des tableaux et des dictionnaires peuvent être utilisés.
# 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
Lançons-le. Lorsqu'il est exécuté avec l'option v, les résultats sont affichés pour chaque méthode de test. Le nom de la méthode doit commencer par test pour que le test s'exécute.
$ 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 ===============================================================================
Au fait, que se passe-t-il si vous donnez 0 ou un nombre négatif à `` get_fibonacci_by_index (x) ''? Jusqu'à présent, vous n'avez donné que des nombres naturels.
Quand j'ai donné 0 et -1, j'ai obtenu 1. Est-ce le comportement prévu?
>>> import my_math; my_math.get_fibonacci_by_index(0)
1
>>> import my_math; my_math.get_fibonacci_by_index(-1)
1
En regardant le code source, il semble qu'il renvoie 1 à moins qu'il n'entre dans `` range (1, x) ''.
Il est important de rédiger un test en pensant à divers cas, mais il est difficile d'en atteindre trop. Par exemple, que se passe-t-il si une chaîne entre en tant qu'argument? Et si la valeur booléenne venait? Etc.
Dans ce get_fibonacci_by_index (x)
, (x) devrait être pour les nombres naturels.
Par conséquent, il devrait être possible de définir que seuls les nombres naturels sont supposés.
... mais cette fois, écrivons un test! Alors faisons un petit détour. Voir le cas de test ci-dessous.
def test_bool(self):
assert my_math.get_fibonacci_by_index(True) == 1
assert my_math.get_fibonacci_by_index(False) == 1
Ce test réussit de manière inattendue.
La raison est que
True, Falsepeut être évalué comme
Int```, qui vaut respectivement 1,0.
>>> int(True)
1
>>> int(False)
0
À l'avenir, si vous ajoutez une implémentation qui vérifie strictement le type, ce test risque de ne pas réussir.
Cependant, le cas où True, False '' est spécifié ne doit pas être le modèle voulu. Par conséquent, écrivons un test qui attend cette fois
TypeError ''.
pytest.Vous pouvez écrire des tests qui s'attendent à des exceptions en utilisant des levées conjointement avec la clause with.
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)
Mais bien sûr, le test échoue.
Cela n'a pas l'air très bien de le laisser dans cet état ...
$ 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 ==========================================================================
Alors sautons ce test une fois.
## Passer le test
Utilisons pytest comme décorateur.
#### **`pytest.mark.Vous pouvez ignorer le test cible en utilisant skip.`**
Ajoutez
pytest``` à l'importation.
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)
Vous pouvez également spécifier les conditions à ignorer.
sys.version_info est un idiome pour obtenir la version Python.
Bien sûr, n'oubliez pas d'importer sys.
import sys .. @pytest.mark.skipif(sys.version_info < (3,5), reason="requires python 3.5") def test_requires_35(self): assert True
Si vous l'exécutez sur Python 2.7.11 et Python 3.5.2 respectivement, vous pouvez voir que le test cible est ignoré dans 2.7.11.
$ 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
Cela est utile lorsque vous utilisez une fonction qui est implémentée uniquement dans une version spécifique, ou lorsque vous implémentez un module qui prend en charge plusieurs versions.
De plus, `` pyenv '' est utile lors du basculement entre les versions de Python à exécuter.
(L'explication de pyenv est différente du contenu de ce chapitre, je vais donc l'omettre.)
- https://github.com/pyenv/pyenv
## Ajuster l'ordre des importations
Si vous écrivez le code comme ci-dessus, les trois importations suivantes doivent être écrites.
import sys
import pytest
import my_math
En fait, il existe également des outils pour ajuster cet ordre.
Vous pouvez utiliser isort pour trier les importations.
(Il existe diverses autres fonctions, mais ce n'est qu'une brève introduction.)
- https://github.com/timothycrosley/isort
Eh bien, j'ai pu écrire le test en toute sécurité. C'est très facile!
Lorsque vous ajoutez du code, vous pouvez prendre l'habitude d'écrire des tests pour réduire les erreurs d'implémentation.
## la prochaine fois
Je veux écrire des tests pour des méthodes complexes en Python! est.
Recommended Posts