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.
@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.
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.
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.
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():
...