web-dev-qa-db-fra.com

L'utilisation de py.test avec couverture n'inclut pas les importations

Pour Jedi nous voulons générer notre couverture de test . Il y a question connexe dans stackoverflow, mais cela n'a pas aidé.

Nous utilisons py.test comme testeur. Cependant, nous ne pouvons pas ajouter les importations et autres éléments "importés" au rapport. Par exemple __init__.py est toujours signalé comme étant découvert:

Name                           Stmts   Miss  Cover
--------------------------------------------------
jedi/__init__                      5      5     0%
[..]

Il est clair que ce fichier est en cours d'importation et doit donc être signalé comme testé.

Nous commençons des tests comme celui-ci [*]:

py.test --cov jedi

Comme vous pouvez le voir, nous utilisons pytest-coverage.

Alors, comment est-il possible de compter correctement la couverture des fichiers comme __init__.py?

[*] Nous avons également essayé de démarrer le test sans --doctest-modules (supprimé de pytest.ini) et activez le module de couverture plus tôt par py.test -p pytest_cov --cov jedi. Aucun d'eux ne fonctionne.

J'ai offert une prime. Veuillez essayer de le corriger dans Jedi. Il est accessible au public.

39
Dave Halter

@hynekcer m'a donné la bonne idée. Mais fondamentalement, la solution la plus simple se trouve ailleurs:

Se débarrasser de pytest-cov!

Utilisation

coverage run --source jedi -m py.test
coverage report

au lieu!!! De cette façon, vous exécutez simplement une couverture sur votre configuration py.test actuelle, qui fonctionne parfaitement bien! C'est aussi philosophiquement la bonne voie à suivre: faire en sorte que chaque programme fasse bien une chose - py.test exécute des tests et coverage vérifie la couverture du code.

Maintenant, cela peut ressembler à une diatribe, mais vraiment. pytest-cov ne fonctionne pas correctement depuis un moment maintenant. Certains tests ont échoué, simplement parce que nous l'avons utilisé.


En date du 2014, pytest-cov semble avoir changé de mains. py.test --cov jedi test semble à nouveau être une commande utile (regardez les commentaires). Cependant, vous n'avez pas besoin de l'utiliser. Mais en combinaison avec xdist, cela peut accélérer vos rapports de couverture.

65
Dave Halter

J'ai fixé la couverture de test à 94% par ce patch qui simplifie les dépendances d'importation et par la commande:

py.test --cov jedi test                    # or
py.test --cov jedi test --cov-report=html  # + a listing with red uncovered lines

Les lignes non couvertes ne se trouvent que dans les commandes conditionnelles ou dans certaines fonctions moins utilisées, mais tous les en-têtes sont entièrement couverts.

Le problème était que la configuration des tests test/conftest.py a importé prématurément par dépendances presque tous les fichiers du projet. Le fichier conftest définit également des options et des paramètres de ligne de commande supplémentaires qui doivent être définis avant d'exécuter le test. Par conséquent, je pense que le plugin pytest_cov fonctionne correctement s'il ignore tout ce qui a été importé avec ce fichier, bien que ce soit pénible. J'ai également exclu __init__.py et settings.py du rapport car ils sont simples et avec une couverture complète mais ils sont aussi importés prématurément dans la dépendance de conftest.

8
hynekcer

Dans mon cas, tous les tests sont exécutés, mais la couverture était de 0%.

Le correctif était:

$ export PYTHONPATH="."

Après les résultats étaient corrects.

J'ai eu par le passé quelques problèmes avec la commande py.test Ayant des problèmes pour importer quelque chose et la définition de PYTHONPATH env var était la solution. Cela a fonctionné pour moi cette fois aussi.

Mon vrai exemple avec awslogs

Tout d'abord avec PYTHONPATH unset:

$ py.test --cov=awslogs  tests/
========================================= test session starts =========================================
platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile:
plugins: cov-2.2.0
collected 11 items

tests/test_it.py ...........Coverage.py warning: No data was collected.

--------------------------- coverage: platform linux2, python 2.7.9-final-0 ---------------------------
Name                    Stmts   Miss  Cover
-------------------------------------------
awslogs/__init__.py         2      2     0%
awslogs/bin.py             85     85     0%
awslogs/core.py           143    143     0%
awslogs/exceptions.py      12     12     0%
-------------------------------------------
TOTAL                     242    242     0%

====================================== 11 passed in 0.38 seconds ======================================

La couverture résultante est de 0%.

Ensuite, j'ai défini le PYTHONPATH:

$ export PYTHONPATH="."

et relancez le test:

$ py.test --cov=awslogs  tests/
========================================= test session starts =========================================
platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile:
plugins: cov-2.2.0
collected 11 items

tests/test_it.py ...........
--------------------------- coverage: platform linux2, python 2.7.9-final-0 ---------------------------
Name                    Stmts   Miss  Cover
-------------------------------------------
awslogs/__init__.py         2      0   100%
awslogs/bin.py             85      9    89%
awslogs/core.py           143     12    92%
awslogs/exceptions.py      12      2    83%
-------------------------------------------
TOTAL                     242     23    90%

====================================== 11 passed in 0.44 seconds ======================================

La couverture est maintenant de 90%.

AVERTISSEMENT : La manipulation de PYTHONPATH peut avoir des effets secondaires étranges. Actuellement, je rencontre un problème, ce package basé sur pbr crée le répertoire Egg lors de la construction distribuable et si PYTHONPATH est défini sur ".", Il considère automatiquement le package lié à Egg comme installé. Pour cette raison, j'ai cessé d'utiliser pytest-cov Et j'ai suivi les conseils pour utiliser l'outil coverage à la place.

5
Jan Vlcinsky

J'ai eu ce problème avec py.test, la couverture et le Django. Apparemment, les fichiers de modèle sont importés avant le début de la couverture. Pas même "-p couverture" pour le chargement anticipé de la couverture -plugin a fonctionné.

Je l'ai corrigé (moche?) En supprimant le module models de sys.modules et en le réimportant dans le fichier de test qui teste le modèle:

import sys
del sys.modules['project.my_app.models']
from project.my_app import models

def test_my_model():
  ...
2
Fabian Kreutz