Test Python avec pytest. Plugins CHAPITRE 5

Retour Suivant


Un pytest puissant dÚs la sortie de la boßte, il devient encore meilleur lorsque vous y ajoutez un mélange de plugins. La base de code pytest est structurée par des paramÚtres et des extensions, et il existe des crochets disponibles pour la modification et l'amélioration via des plugins.



Les exemples de ce livre sont écrits en utilisant Python 3.6 et pytest 3.2. pytest 3.2 prend en charge Python 2.6, 2.7 et Python 3.3+.


Le code source du projet Tùches, ainsi que pour tous les tests présentés dans ce livre, est disponible sur le lien sur la page Web du livre à pragprog.com . Vous n'avez pas besoin de télécharger le code source pour comprendre le code de test; le code de test est présenté sous une forme pratique dans les exemples. Mais pour suivre les tùches du projet ou adapter des exemples de test pour tester votre propre projet (vos mains ne sont pas liées!), Vous devez vous rendre sur la page Web du livre et télécharger le travail. Là, sur la page Web du livre, il y a un lien pour les messages d' erreur et un forum de discussion .

Sous le spoiler se trouve une liste d'articles de cette série.



Allons plus loin!


Vous pourriez ĂȘtre surpris d'apprendre que vous avez dĂ©jĂ  Ă©crit des plugins si vous avez parcouru les chapitres prĂ©cĂ©dents de ce livre. Chaque fois que vous placez des fixtures et / ou des fonctions de hook dans le fichier conftest.py niveau conftest.py du projet, vous crĂ©ez un plugin conftest local. C'est juste un peu de travail supplĂ©mentaire pour convertir ces fichiers conftest.py en plugins installables que vous pouvez partager entre projets, avec d'autres personnes ou avec le monde.


Nous commençons ce chapitre en rĂ©pondant Ă  la question de savoir oĂč chercher des plugins tiers. Un certain nombre de plugins sont disponibles, il y a donc de fortes chances que quelqu'un ait dĂ©jĂ  Ă©crit les modifications que vous souhaitez apporter dans pytest . Puisque nous considĂ©rerons les plugins open source, si le plugin fait presque ce que vous voulez faire, mais pas tout Ă  fait, vous pouvez le dĂ©velopper, ou l'utiliser comme rĂ©fĂ©rence pour crĂ©er votre propre plugin. Bien que ce chapitre traite de la crĂ©ation de vos propres plugins, l'annexe 3, le plugin Sampler Pack , Ă  la page 163 est incluse pour vous donner un avant-goĂ»t de ce qui est possible.


Dans ce chapitre, vous apprendrez Ă  crĂ©er des plugins et je vous montrerai la bonne direction pour les tests, le packaging et la distribution. Le sujet complet de l'emballage et de la distribution Python est trop vaste et prĂ©tend ĂȘtre son propre livre, nous ne couvrirons donc pas tout. Mais vous obtiendrez suffisamment d'informations pour pouvoir Ă©changer des plugins avec votre Ă©quipe. Je parlerai Ă©galement de quelques façons simples de crĂ©er des plugins avec le support PyPI et le moins de travail.


Plugins de recherche


Vous pouvez trouver des plugins tiers pytest Ă  plusieurs endroits. Les plugins rĂ©pertoriĂ©s dans l'annexe 3, Plugin Sampler Pack, Ă  la page 163, peuvent ĂȘtre tĂ©lĂ©chargĂ©s Ă  partir de PyPI. Cependant, ce n'est pas le seul endroit pour trouver de super plugins pytest.


https://docs.pytest.org/en/latest/plugins.html


Le site principal de documentation de pytest a une page qui parle de l'installation et de l'utilisation des plugins pytest et répertorie certains plugins courants.


https://pypi.python.org


L'index des packages Python (PyPI) est un excellent endroit pour obtenir beaucoup de packages Python, mais aussi un excellent endroit pour rechercher des plugins pytest. Lorsque vous recherchez des plugins pytest, entrez simplement «pytest», «pytest -» ou «-pytest» dans le champ de recherche, car la plupart des plugins pytest commencent par «pytest -» ou se terminent par «-pytest».


https://github.com/pytest-dev


Le groupe pytest-dev sur GitHub est l'endroit oĂč le code source pytest est stockĂ©. De plus, vous pouvez trouver ici des plugins pytest populaires qui devraient ĂȘtre pris en charge Ă  long terme par l'Ă©quipe du noyau pytest.


Installation du plugin


Les plugins Pytest sont installés avec pip, comme les autres packages Python. Cependant
vous pouvez utiliser pip de plusieurs maniĂšres pour installer des plugins.


Installer depuis PyPI


Étant donnĂ© que PyPI est l'emplacement par dĂ©faut pour pip, l'installation de plugins Ă  partir de PyPI est la mĂ©thode la plus simple. pytest-cov plugin pytest-cov :


 $ pip install pytest-cov 

La derniÚre version stable de PyPI sera installée.


Installer une version spécifique de PyPI


Si vous voulez une version spécifique du plugin, vous pouvez spécifier la version aprÚs == :


 $ pip install pytest-cov==2.4.0 

Installer Ă  partir d'un fichier .tar.gz ou .whl


Les packages PyPI sont distribués sous forme de fichiers zip avec les extensions .tar.gz et / ou .whl . Ils sont souvent appelés boules de goudron et roues. Si vous rencontrez des problÚmes pour essayer de travailler directement avec PyPI (ce qui peut se produire avec les pare-feu et autres complications réseau), vous pouvez télécharger .tar.gz ou .whl et installer à partir de ceci ou cela.


Vous n'avez pas besoin de déballer ou de danser avec un tambourin; il suffit de pointer pip dessus:


 $ pip install pytest-cov-2.4.0.tar.gz # or $ pip install pytest_cov-2.4.0-py2.py3-none-any.whl 

Installation à partir du répertoire local


Vous pouvez avoir les plugins pour les plugins (et d'autres packages Python) dans un répertoire local ou partagé au .whl .tar.gz ou .whl et l'utiliser à la place de PyPI pour installer les plugins:


 $ mkdir some_plugins $ cp pytest_cov-2.4.0-py2.py3-none-any.whl some_plugins/ $ pip install --no-index --find-links=./some_plugins/ pytest-cov 

--no-index indique à pip ne pas se connecter à PyPI. --find-links=./some_plugins/ indique à pip de chercher dans le répertoire some_plugins . Cette méthode est particuliÚrement utile si vous avez à la fois des tiers et vos propres plugins stockés localement, ainsi que si vous créez de nouveaux environnements virtuels pour une intégration continue ou avec tox. (Nous parlerons à la fois de tox et d'intégration continue dans le chapitre 7, à l'aide de pytest avec d'autres outils, à la page 125.)


Veuillez noter qu'en utilisant la méthode d'installation du répertoire local, vous pouvez installer plusieurs versions et spécifier la version souhaitée en ajoutant == et le numéro de version:


 $ pip install --no-index --find-links=./some_plugins/ pytest-cov==2.4.0 

Installer à partir du référentiel Git


Vous pouvez installer des plugins directement depuis le référentiel Git dans ce cas GitHub:


 $ pip install git+https://github.com/pytest-dev/pytest-cov 

Vous pouvez également spécifier la balise de version:


 $ pip install git+https://github.com/pytest-dev/pytest-cov@v2.4.0 

Ou vous pouvez spécifier une branche:


 $ pip install git+https://github.com/pytest-dev/pytest-cov@master 

L'installation à partir du référentiel Git est particuliÚrement utile si vous stockez votre propre travail dans Git ou si la version requise du plugin ou du plugin est manquante dans PyPI.


Note du traducteur:

pip prend en charge l'installation de Git, Mercurial, Subversion et Bazaar et définit le type VCS en utilisant les préfixes d'URL: "git +", "hg +", "svn +", "bzr +".
Voir la documentation PyPI pour plus de détails.

Écrire vos propres plugins


De nombreux plugins tiers contiennent beaucoup de code. C'est l'une des raisons pour lesquelles nous les utilisons pour nous faire gagner du temps Ă  dĂ©velopper tout cela par nous-mĂȘmes. Cependant, pour votre code spĂ©cifique, vous trouverez sans aucun doute des installations et des modifications spĂ©ciales pour vous aider Ă  le tester. En crĂ©ant un plugin, vous pouvez facilement partager mĂȘme plusieurs appareils que vous souhaitez partager entre plusieurs projets. Vous pouvez partager ces changements avec plusieurs projets - et Ă©ventuellement avec le reste du monde - en dĂ©veloppant et en distribuant vos propres plugins. C'est assez facile Ă  faire. Dans cette section, nous allons dĂ©velopper une petite modification du comportement de pytest, l'emballer sous forme de plugin, le tester et rĂ©flĂ©chir Ă  sa distribution.


Les plugins peuvent inclure des fonctions de hook qui modifient le comportement de pytest. Puisque pytest a Ă©tĂ© conçu pour permettre aux plugins de modifier lĂ©gĂšrement le comportement de pytest, de nombreuses fonctions de hook sont disponibles. les crochets pour pytest sont rĂ©pertoriĂ©s sur le site de documentation de pytest . Dans notre exemple, nous allons crĂ©er un plugin qui changera l'apparence du statut du test. Ajoutez un paramĂštre de ligne de commande pour activer ce nouveau comportement. Ajoutez du texte Ă  l'en-tĂȘte de sortie. En particulier, nous changerons tous les indicateurs d'Ă©tat ÉCHEC (Ă©chouĂ©) en «OPPORTUNITÉ (potentielle) pour amĂ©lioration», changer F en O et ajouter «Merci d'avoir exĂ©cutĂ© les tests» dans l'en-tĂȘte. Pour ce faire, nous utiliserons l'option --nice .


Pour garder les changements de comportement sĂ©parĂ©s de la discussion sur la mĂ©canique des plugins, nous apporterons des modifications Ă  conftest.py avant de le transformer en plugin redistribuable. Vous n'avez pas besoin d'exĂ©cuter les plugins de cette façon. Mais souvent, les modifications que vous aviez l'intention d'utiliser dans un seul projet seront suffisamment utiles pour ĂȘtre partagĂ©es et transformĂ©es en plug-in. Par consĂ©quent, nous commençons par ajouter des fonctionnalitĂ©s au fichier conftest.py, puis, une fois que tout fonctionne dans conftest.py, nous dĂ©plaçons le code dans le package.


Retour au projet Tùches. Dans la section «En attente d'exceptions» à la page 30, nous avons écrit plusieurs tests qui vérifiaient si des exceptions étaient levées si quelqu'un appelait la fonction API de maniÚre incorrecte. Il semble que nous ayons raté au moins quelques états d'erreur possibles.


Voici quelques tests supplémentaires:


ch5 / a / tasks_proj / tests / func / test_api_exceptions.py

 """     API wrong.""" import pytest import tasks from tasks import Task @pytest.mark.usefixtures('tasks_db') class TestAdd(): """,   tasks.add().""" def test_missing_summary(self): """  ,  summary missing.""" with pytest.raises(ValueError): tasks.add(Task(owner='bob')) def test_done_not_bool(self): """  ,  done   bool.""" with pytest.raises(ValueError): tasks.add(Task(summary='summary', done='True')) 

Exécutons-les pour vérifier s'ils réussissent:


 $ cd /path/to/code/ch5/a/tasks_proj $ pytest ===================== test session starts ====================== collected 57 items tests/func/test_add.py ... tests/func/test_add_variety.py ............................ tests/func/test_add_variety2.py ............ tests/func/test_api_exceptions.py .F....... tests/func/test_unique_id.py . tests/unit/test_task.py .... =========================== FAILURES =========================== __________________ TestAdd.test_done_not_bool __________________ self = <func.test_api_exceptions.TestAdd object at 0x103a71a20> def test_done_not_bool(self): """Should raise an exception if done is not a bool.""" with pytest.raises(ValueError): > tasks.add(Task(summary='summary', done='True')) E Failed: DID NOT RAISE <class 'ValueError'> tests/func/test_api_exceptions.py:20: Failed ============= 1 failed, 56 passed in 0.28 seconds ============== 

Exécutons-le à nouveau avec -v pour plus de détails. Puisque vous avez déjà vu la trace, vous pouvez la désactiver en appuyant sur --tb=no .


Concentrons-nous maintenant sur les nouveaux tests avec -k TestAdd , qui fonctionne car il n'y a pas d'autres tests avec des noms qui contiennent «TestAdd».


Nous pourrions «tout laisser tomber» et essayer de corriger ce test (et nous le ferons plus tard), mais nous allons maintenant nous concentrer sur la tentative de rendre les échecs plus agréables pour les développeurs.


Commençons par ajouter un message de remerciement Ă  l'en-tĂȘte, ce que vous pouvez faire avec un crochet pytest_report_header() appelĂ© pytest_report_header() .


ch5 / b / tasks_proj / tests / conftest.py

 def pytest_report_header(): """    .""" return "Thanks for running the tests." 

De toute Ă©vidence, taper une note de remerciement est assez stupide. Cependant, la possibilitĂ© d'ajouter des informations Ă  l'en-tĂȘte peut ĂȘtre Ă©tendue. Vous pouvez ajouter un nom d'utilisateur, indiquer l'Ă©quipement utilisĂ© et les versions Ă  tester. En gĂ©nĂ©ral, tout ce que vous pouvez convertir en chaĂźne peut ĂȘtre insĂ©rĂ© dans le titre du test.


Ensuite, nous changerons le rapport d'état du test pour changer F en O et FAILED en OPPORTUNITY for improvement . Il y a un hook qui permet cette affaire: pytest_report_teststatus() :


ch5 / b / tasks_proj / tests / conftest.py

 def pytest_report_teststatus(report): """   .""" if report.when == 'call' and report.failed: return (report.outcome, 'O', 'OPPORTUNITY for improvement') 

Et maintenant, nous avons juste la solution que nous recherchions. Une session de test sans l'indicateur --verbose affiche O pour les échecs, c'est-à-dire que des améliorations sont possibles:


 $ cd /path/to/code/ch5/b/tasks_proj/tests/func $ pytest --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py .O ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.06 seconds ======= 

Avec le drapeau -v ou --verbose , ce serait mieux:


 $ pytest -v --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py::TestAdd::test_missing_summary PASSED test_api_exceptions.py::TestAdd::test_done_not_bool OPPORTUNITY for improvement ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds ======= 

La derniÚre modification que nous apporterons consiste à ajouter un paramÚtre de ligne de commande, --nice, afin que les modifications de notre état ne se produisent que si vous remplacez --nice :


 def pytest_addoption(parser): """ nice    --nice.""" group = parser.getgroup('nice') group.addoption("--nice", action="store_true", help="nice: turn failures into opportunities") def pytest_report_header(): """    .""" if pytest.config.getoption('nice'): return "Thanks for running the tests." def pytest_report_teststatus(report): """   .""" if report.when == 'call': if report.failed and pytest.config.getoption('nice'): return (report.outcome, 'O', 'OPPORTUNITY for improvement') 

Il convient de noter que pour ce plugin, nous n'utilisons que quelques crochets. Il y en a beaucoup d'autres sur le site de documentation principal de Pytest .


Maintenant, nous pouvons tester manuellement notre plugin en l'exécutant simplement dans notre exemple. Tout d'abord, sans l'option --nice , pour vous assurer que seul le nom d'utilisateur est affiché:


 $ cd /path/to/code/ch5/c/tasks_proj/tests/func $ pytest --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== collected 9 items test_api_exceptions.py .F ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds ======= 

Maintenant avec --nice :


 $ pytest --nice --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py .O ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds ======= 

Maintenant avec --nice et --verbose :


 $ pytest -v --nice --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py::TestAdd::test_missing_summary PASSED test_api_exceptions.py::TestAdd::test_done_not_bool OPPORTUNITY for improvement ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.06 seconds ======= 

Super! Toutes les modifications que nous voulions apporter ont été effectuées dans une dizaine de lignes de code pour le fichier conftest.py . Ensuite, nous déplacerons ce code dans la structure du plugin.


Création d'un plugin installable


Le processus de partage des plugins avec d'autres utilisateurs est clairement dĂ©fini. MĂȘme si vous n'activez jamais votre propre plugin dans PyPI, passer par ce processus vous facilitera la lecture du code Ă  partir des plugins open source, et vous aurez plus d'occasions d'Ă©valuer s'ils vous aideront ou non.


Il serait superflu de couvrir entiÚrement le conditionnement et la distribution des packages Python dans ce livre, car ce sujet est bien documenté ailleurs. Ici et ici et ici en russe. Cependant, passer du plug-in de configuration local que nous avons créé dans la section précédente à quelque chose installé à l'aide de pip n'est pas un gros problÚme. ,


Tout d'abord, nous devons créer un nouveau répertoire pour héberger notre code de plugin. Peu importe comment vous l'appelez, mais comme nous créons un plugin pour le joli drapeau, appelons-le pytest-nice. Nous aurons deux fichiers dans ce nouveau répertoire: pytest_nice.py et setup.py. (Le catalogue de tests sera discuté dans la section «Plugins de test» à la page 105.)


 │ LICENSE │ pytest_nice.py │ setup.py │ └───tests │ conftest.py │ test_nice.py 

Dans pytest_nice.py , nous mettons le contenu exact de notre conftest.py qui était associé à cette fonction (et l'extrayons de tasks_proj/tests/conftest.py ):


ch5 / pytest-nice / pytest_nice.py


 """  pytest-nice .""" import pytest def pytest_addoption(parser): """ nice    --nice.""" group = parser.getgroup('nice') group.addoption("--nice", action="store_true", help="nice: turn FAILED into OPPORTUNITY for improvement") def pytest_report_header(): """    .""" if pytest.config.getoption('nice'): return "Thanks for running the tests." def pytest_report_teststatus(report): """   .""" if report.when == 'call': if report.failed and pytest.config.getoption('nice'): return (report.outcome, 'O', 'OPPORTUNITY for improvement') 

Dans setup.py nous avons besoin de l'appel le plus minimal pour setup() :


ch5 / pytest-nice / setup.py

 """Setup  pytest-nice plugin.""" from setuptools import setup setup( name='pytest-nice', version='0.1.0', description=' Pytest,   FAILURE into OPPORTUNITY', url='https:////////', author=' ', author_email='your_email@somewhere.com', license='proprietary', py_modules=['pytest_nice'], install_requires=['pytest'], entry_points={'pytest11': ['nice = pytest_nice', ], }, ) 

Vous aurez besoin de plus d'informations dans les paramÚtres si vous souhaitez les diffuser à un large public ou sur Internet. Cependant, pour une petite équipe ou juste pour vous, ce sera suffisant.


Vous pouvez inclure d'autres paramĂštres pour setup() ; et ici nous n'avons que les champs obligatoires. Le champ version est la version de ce plugin. Et cela dĂ©pend entiĂšrement de vous lorsque vous montez la version. Le champ URL est obligatoire. Vous pouvez le laisser vide, mais vous obtiendrez un avertissement. Les author_email author et author_email peuvent ĂȘtre remplacĂ©s par author_email et author_email , mais l'une de ces paires doit ĂȘtre lĂ . Le champ de license est un champ de texte court. Cela peut ĂȘtre l'une des nombreuses licences open source, votre nom ou votre entreprise, ou quelque chose qui vous convient. L' py_modules rĂ©pertorie pytest_nice comme notre seul module pour ce plugin. Bien qu'il s'agisse d'une liste et que vous pouvez inclure plusieurs modules, si j'en avais plusieurs, j'utiliserais le package et mettrais tous les modules dans un rĂ©pertoire.


Jusqu'à présent, toutes les options setup() sont standard et sont utilisées par tous les installateurs Python. La partie qui est différente pour les plugins Pytest est le paramÚtre entry_points . Nous avons répertorié entry_points={'pytest11': ['nice = pytest_nice', ], },. La fonction entry_points est standard pour setuptools , mais pytest11 est l'identifiant spécial que pytest recherche. Dans cette ligne, nous disons à pytest que nice est le nom de notre plugin, et pytest_nice nom du module dans lequel notre plugin vit. Si nous avons utilisé le package, notre entrée ici serait:


Je n'ai pas encore parlé du fichier README.rst . Une certaine forme de README est une exigence de setuptools. Si vous le manquez, vous obtiendrez ceci:


 ... warning: sdist: standard file not found: should have one of README, README.rst, README.txt ... 

Garder README comme moyen standard d'inclure des informations sur le projet est de toute façon une bonne idée. Voici ce que j'ai mis dans le fichier pour pytest-nice:


ch5 / pytest-nice / README.rst

 pytest-nice : A pytest plugin =============================   pytest     .  -------- -   ,     pytest. -  ``--nice`` , : -  ``F``  ``O`` -  ``-v``,  ``FAILURE``  ``OPPORTUNITY for improvement``  ------------ ,    Pytest    .tar.gz    PATH,  : :: $ pip install PATH/pytest-nice-0.1.0.tar.gz $ pip install --no-index --find-links PATH pytest-nice  ----- :: $ pytest --nice 

Il existe de nombreuses opinions sur ce qui devrait ĂȘtre dans le fichier README. Il s'agit d'une version fortement recadrĂ©e, mais cela fonctionne.


Test des plugins


Les plugins sont du code qui doit ĂȘtre testĂ© comme tout autre code. Cependant, tester les modifications apportĂ©es Ă  un outil de test est un peu plus compliquĂ©. Lorsque nous avons dĂ©veloppĂ© le code du plugin dans la section «Écriture de vos propres plugins», Ă  la page 98, nous l'avons vĂ©rifiĂ© manuellement Ă  l'aide d'un exemple de fichier de test, en exĂ©cutant pytest avec lui et en vĂ©rifiant la sortie pour vous assurer qu'elle Ă©tait correcte. Nous pouvons faire de mĂȘme en mode automatique en utilisant un plugin appelĂ© pytester , qui vient avec pytest mais est dĂ©sactivĂ© par dĂ©faut.


Il y a deux fichiers dans notre répertoire test pour pytest-nice: conftest.py et test_nice.py . Pour utiliser pytester , nous devons ajouter une seule ligne à conftest.py :


ch5 / pytest-nice / tests / conftest.py

 """pytester is needed for testing plugins.""" pytest_plugins = 'pytester' 

Cette ligne inclut le plugin pytester . Nous utiliserons un appareil appelé testdir , qui devient disponible lorsque le pytester activé.
Souvent, les tests de plugins prennent la forme que nous avons décrite manuellement:


  1. Créez un exemple de fichier de test.
  2. Exécutez pytest avec ou sans certains paramÚtres dans le répertoire qui contient l'exemple de fichier.
  3. Vérifiez la sortie.
  4. Possible, pour vérifier le code de résultat est 0 pour toutes les passes, 1 pour certains échecs.

Regardons un exemple:


ch5 / pytest-nice / tests / test_nice.py

 def test_pass_fail(testdir): #     Pytest testdir.makepyfile(""" def test_pass(): assert 1 == 1 def test_fail(): assert 1 == 2 """) #  pytest result = testdir.runpytest() # fnmatch_lines    result.stdout.fnmatch_lines([ '*.F', # .  Pass, F  Fail ]) # ,      '1'  testsuite assert result.ret == 1 

Fixture testdir crée automatiquement un répertoire temporaire pour l'hébergement des fichiers de test. Il a une méthode makepyfile() qui vous permet de mettre le contenu d'un fichier de makepyfile() ce cas, nous créons deux tests: l'un qui passe et l'autre qui ne passe pas .


Nous exĂ©cutons pytest pour un nouveau fichier de test en utilisant testdir.runpytest() . Vous pouvez transmettre des paramĂštres si vous le souhaitez. La valeur de retour peut ĂȘtre considĂ©rĂ©e ultĂ©rieurement et est de type RunResult .


Habituellement, je regarde stdout et ret . , , , fnmatch_lines , , , , ret 0 1 . , fnmatch_lines , . . , , :


ch5/pytest-nice/tests/test_nice.py

 @pytest.fixture() def sample_test(testdir): testdir.makepyfile(""" def test_pass(): assert 1 == 1 def test_fail(): assert 1 == 2 """) return testdir 

, , sample_test , . :


ch5/pytest-nice/tests/test_nice.py

 def test_with_nice(sample_test): result = sample_test.runpytest('--nice') result.stdout.fnmatch_lines(['*.O', ]) # . for Pass, O for Fail assert result.ret == 1 def test_with_nice_verbose(sample_test): result = sample_test.runpytest('-v', '--nice') result.stdout.fnmatch_lines([ '*::test_fail OPPORTUNITY for improvement', ]) assert result.ret == 1 def test_not_nice_verbose(sample_test): result = sample_test.runpytest('-v') result.stdout.fnmatch_lines(['*::test_fail FAILED']) assert result.ret == 1 

. , :


ch5/pytest-nice/tests/test_nice.py

 def test_header(sample_test): result = sample_test.runpytest('--nice') result.stdout.fnmatch_lines(['Thanks for running the tests.']) def test_header_not_nice(sample_test): result = sample_test.runpytest() thanks_message = 'Thanks for running the tests.' assert thanks_message not in result.stdout.str() 

, , .


:


ch5/pytest-nice/tests/test_nice.py

 def test_help_message(testdir): result = testdir.runpytest('--help') # fnmatch_lines    result.stdout.fnmatch_lines([ 'nice:', '*--nice*nice: turn FAILED into OPPORTUNITY for improvement', ]) 

, , , .


pytest-nice , . .zip.gz , :


 $ cd /path/to/code/ch5/pytest-nice/ $ pip install . Processing /path/to/code/ch5/pytest-nice Requirement already satisfied: pytest in /path/to/venv/lib/python3.6/site-packages (from pytest-nice==0.1.0) Requirement already satisfied: py>=1.4.33 in /path/to/venv/lib/python3.6/site-packages (from pytest->pytest-nice==0.1.0) Requirement already satisfied: setuptools in /path/to/venv/lib/python3.6/site-packages (from pytest->pytest-nice==0.1.0) Building wheels for collected packages: pytest-nice Running setup.py bdist_wheel for pytest-nice ... done ... Successfully built pytest-nice Installing collected packages: pytest-nice Successfully installed pytest-nice-0.1.0 

, , :


 $ pytest -v ===================== test session starts ====================== plugins: nice-0.1.0 collected 7 items tests/test_nice.py::test_pass_fail PASSED tests/test_nice.py::test_with_nice PASSED tests/test_nice.py::test_with_nice_verbose PASSED tests/test_nice.py::test_not_nice_verbose PASSED tests/test_nice.py::test_header PASSED tests/test_nice.py::test_header_not_nice PASSED tests/test_nice.py::test_help_message PASSED =================== 7 passed in 0.34 seconds =================== 

. : , . .
 platform win32 -- Python 3.6.5, pytest-3.9.3, py-1.7.0, pluggy-0.8.0 -- c:\venv36\scripts\python.exe collected 7 items tests/test_nice.py::test_pass_fail FAILED [ 14%] tests/test_nice.py::test_with_nice OPPORTUNITY for improvement [ 28%] tests/test_nice.py::test_with_nice_verbose OPPORTUNITY for improvement [ 42%] tests/test_nice.py::test_not_nice_verbose FAILED [ 57%] tests/test_nice.py::test_header PASSED [ 71%] tests/test_nice.py::test_header_not_nice PASSED [ 85%] tests/test_nice.py::test_help_message PASSED [100%] ================================== FAILURES =================================== _______________________________ test_pass_fail ________________________________ 



  result.stdout.fnmatch_lines([ '*.F', # . for Pass, F for Fail ]) 


sur
  result.stdout.fnmatch_lines([ '*.F*', # . for Pass, F for Fail ]) 


* F

test_with_nice , test_with_nice_verbose , test_not_nice_verbose

pytest.
c
'test_with_nice.py .O [100%]'
.
,

RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead

!
 (venv36) c:\_BOOKS_\pytest_si\bopytest-code\code\ch5\pytest-nice>pytest -v ============================= test session starts ============================= platform win32 -- Python 3.6.5, pytest-3.9.3, py-1.7.0, pluggy-0.8.0 -- c:\venv36\scripts\python.exe cachedir: .pytest_cache rootdir: c:\_BOOKS_\pytest_si\bopytest-code\code\ch5\pytest-nice, inifile: plugins: nice-0.1.0 collected 7 items tests/test_nice.py::test_pass_fail PASSED [ 14%] tests/test_nice.py::test_with_nice PASSED [ 28%] tests/test_nice.py::test_with_nice_verbose PASSED [ 42%] tests/test_nice.py::test_not_nice_verbose PASSED [ 57%] tests/test_nice.py::test_header PASSED [ 71%] tests/test_nice.py::test_header_not_nice PASSED [ 85%] tests/test_nice.py::test_help_message PASSED [100%] ============================== warnings summary =============================== tests/test_nice.py::test_pass_fail c:\venv36\lib\site-packages\_pytest\compat.py:332: RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead return getattr(object, name, default) 

Hourra! . (pytest-nice), Python
pytest-:


 $ pip uninstall pytest-nice Uninstalling pytest-nice-0.1.0: Would remove: \path\to\venv\lib\site-packages\pytest_nice-0.1.0.dist-info\* ... Proceed (y/n)? y Successfully uninstalled pytest-nice-0.1.0 

— , pytest, PyPI.



, . , setup.py :


 $ cd /path/to/code/ch5/pytest-nice $ python setup.py sdist running sdist running egg_info creating pytest_nice.egg-info ... running check creating pytest-nice-0.1.0 ... creating dist Creating tar archive ... $ ls dist pytest-nice-0.1.0.tar.gz 

( , sdist source distribution — “ .”)


pytest-nice dist pytest-nice-0.1.0.tar.gz .


, , :


 $ pip install dist/pytest-nice-0.1.0.tar.gz Processing ./dist/pytest-nice-0.1.0.tar.gz ... Installing collected packages: pytest-nice Successfully installed pytest-nice-0.1.0 

.tar.gz , .



pip , , , , , , .tar.gz . , pytest-nice-0.1.0.tar.gz myplugins .


pytest-nice myplugins :


 $ pip install --no-index --find-links myplugins pytest-nice 

--no-index pip PyPI, , .
The --find-links myplugins tells PyPI to look in myplugins for packages to install. And of course, pytest-nice is what we want to install.
--find-links myplugins PyPI myplugins . , pytest-nice — , .


myplugins , , --upgrade :


 $ pip install --upgrade --no-index --find-links myplugins pytest-nice 

pip , --no-index --find-links myplugins .


PyPI


, , . , . , , , Python Packaging .


pytest, — cookiecutter-pytest-plugin :


 $ pip install cookiecutter $ cookiecutter https://github.com/pytest-dev/cookiecutter-pytest-plugin 

. , . ; , , . pytest, , .


Exercices


ch4/cache/test_slower.py autouse fixture, check_duration() . 4. .


  1. pytest-slower, , , « » . 102.
  2. , pytest-slower , .
  3. Écrivez un code de test pour le plugin.
  4. Jetez un Ɠil Ă  l' index des packages Python et recherchez «pytest-». Trouvez un plugin pytest qui vous semble intĂ©ressant.
  5. Installez le plugin de votre choix et essayez-le sur les tests de tĂąches.

Et ensuite


Vous avez jusqu'à présent utilisé de nombreuses fois conftest.pydans ce livre. Il existe également des fichiers de configuration qui affectent l'exécution de pytest, par exemple pytest.ini. Dans le chapitre suivant, vous vous familiariserez avec les différents fichiers de configuration et découvrirez ce que vous pouvez faire pour vous faciliter la vie lors des tests.


Retour Suivant

Source: https://habr.com/ru/post/fr448794/


All Articles