Je veux écrire en Python! (2) Écrivons un test

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.

L'histoire à présenter cette fois

Il s'agit d'écrire un test. Utilisez pytest.

Je veux écrire un test en Python!

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.

Tester get_fibonacci_by_index ()

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.

Divers affirment

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 ===============================================================================

Test avec des arguments involontaires

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é commeInt```, 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.

Python2.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

Python3.5.2

$ 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

Je veux écrire en Python! (2) Écrivons un test
Je veux faire le test de Dunnett en Python
Je veux créer une fenêtre avec Python
Je veux écrire dans un fichier avec Python
Je veux écrire en Python! (1) Vérification du format de code
Je souhaite intégrer une variable dans une chaîne Python
Je veux facilement implémenter le délai d'expiration en python
Je veux échantillonner au hasard un fichier avec Python
Je veux travailler avec un robot en python.
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux ajouter un joli complément à input () en python
Je veux imprimer dans la notation d'inclusion
Je veux créer un environnement Python
Je veux faire un jeu avec Python
Je ne veux pas passer un test de codage
Je veux fusionner des dictionnaires imbriqués en Python
Je veux afficher la progression en Python!
Je souhaite convertir une table convertie en PDF en Python en CSV
Je veux colorer une partie de la chaîne Excel avec Python
Je veux faire un patch monkey seulement en partie en toute sécurité avec Python
Je veux générer rapidement UUID (memo memo) ~ Edition Python ~
Je veux faire la transition avec un bouton sur le ballon
Même avec JavaScript, je veux voir Python `range ()`!
J'ai essayé d'implémenter un pseudo pachislot en Python
[Python] Je veux faire d'une liste imbriquée un taple
Écrire du code dans UnitTest une application Web Python
Je veux utiliser le jeu de données R avec python
Je veux faire fonctionner un ordinateur quantique avec Python
Je veux faire quelque chose avec Python à la fin
Je veux manipuler des chaînes dans Kotlin comme Python!
Le programme Python est lent! Je veux accélérer! Dans ce cas ...
Ecrire une dichotomie en Python
Ecrire un test piloté par table en C
Ecrire des algorithmes A * (A-star) en Python
Ecrire le code de test du sélénium en python
Ecrire un graphique à secteurs en Python
Ecrire le plugin vim en Python
Écrire une recherche de priorité en profondeur en Python
Je veux déboguer avec Python
J'ai essayé d'implémenter un automate cellulaire unidimensionnel en Python
Je veux faire quelque chose comme sort uniq en Python
[Python] Je souhaite obtenir un ensemble commun entre numpy
Je veux démarrer beaucoup de processus à partir de python
J'ai essayé "Comment obtenir une méthode décorée en Python"
Je souhaite envoyer un message de Python à LINE Bot
J'ai fait un chronomètre en utilisant tkinter avec python
Je veux pouvoir exécuter Python avec VS Code
Je ne voulais pas écrire la clé AWS dans le programme
Je souhaite utiliser une source de données python dans Re: Dash pour obtenir les résultats de la requête.
J'ai essayé d'implémenter PLSA en Python
Je souhaite utiliser un caractère générique que je souhaite décortiquer avec Python remove
J'ai essayé d'implémenter la permutation en Python
J'ai fait un programme de gestion de la paie en Python!
Je veux résoudre APG4b avec Python (seulement 4.01 et 4.04 au chapitre 4)
J'ai essayé d'implémenter PLSA dans Python 2
Je veux utiliser jar de python
Ecrire une courte définition de propriété en Python
Je souhaite rechercher le texte intégral avec elasticsearch + python