web-dev-qa-db-fra.com

Comment utiliser correctement coverage.py en Python?

Je viens de commencer à utiliser le module Coverage.py et j'ai donc décidé de faire un test simple pour vérifier comment cela fonctionne.

Sample.py

def sum(num1, num2):
    return num1 + num2


def sum_only_positive(num1, num2):
    if num1 > 0 and num2 > 0:
        return num1 + num2
    else:
        return None

test.py

from sample import sum, sum_only_positive

def test_sum():
    assert sum(5, 5) == 10

def test_sum_positive_ok():
    assert sum_only_positive(2, 2) == 4

def test_sum_positive_fail():
    assert sum_only_positive(-1, 2) is None

Comme vous le voyez, tout mon code est couvert de tests et py.test dit que tous passent. Je m'attends à ce que Coverage.py affiche une couverture à 100%. Et bien non.

Coverage.py results

Eh bien, Coverage.py peut ne pas voir le fichier test.py, j'ai donc copié les fonctions de test dans sample.py fichier et a exécuté à nouveau la couverture:
enter image description here

J'ai ensuite ajouté ce bloc de code:

if __name__ == "__main__":
    print(sum(2, 4))
    print(sum_only_positive(2, 4))
    print(sum_only_positive(-1, 3))

et supprimé toutes les fonctions de test. Après cela, Coverage.py affiche 100%:

enter image description here

Pourquoi en est-il ainsi? Coverage.py ne devrait-il pas montrer la couverture de test de code, pas seulement la couverture d'exécution? J'ai lu un officiel F.A.Q. pour Coverage.py, mais je ne trouve pas la solution.
Étant donné que de nombreux utilisateurs de SO connaissent les tests de code et la couverture de code, j'espère que vous pourrez me dire où je me trompe.

Je n'ai qu'une seule pensée ici: Coverage.py peut simplement regarder quelles lignes de code ne sont pas exécutées, je devrais donc écrire des tests pour ces lignes. Mais il y a des lignes qui sont déjà exécutées mais qui ne sont pas couvertes de tests, donc Coverage.py échouera ici.

32
Groosha

Coverage recherche un fichier .coverage pour lire et générer ce rapport pour vous. Py.test à lui seul n'en crée pas. Vous avez besoin du plugin py.test pour la couverture:

pip install pytest-cov

Si vous l'avez déjà, vous pouvez exécuter les deux à la fois comme ceci:

py.test test.py --cov=sample.py

Ce qui signifie exécuter le module de test test.py et enregistrer/afficher le rapport de couverture sur sample.py.

Si vous devez effectuer plusieurs tests et accumuler leur couverture enregistrée, puis afficher un rapport final, vous pouvez l'exécuter comme suit:

py.test test.py --cov=sample.py --cov-report=
py.test test.py --cov=sample2.py --cov-report=
py.test test.py --cov=sample3.py --cov-report=

Ce qui signifie exécuter le module de test test.py et enregistrer (uniquement) la couverture sur sample.py - n'affiche pas de rapport.

Vous pouvez maintenant exécuter la commande de couverture séparément pour un rapport complet:

coverage report -m

La commande ci-dessus affiche simplement un rapport de couverture formaté basé sur le fichier de données de couverture accumulé lors des précédents tests. -m signifie afficher les lignes manquées, c'est-à-dire les lignes non couvertes par les tests:

Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       6      0   100%  

La couverture prend en charge plus de commutateurs comme --include et --omit pour inclure/exclure des fichiers à l'aide de modèles de chemin. Pour plus d'informations, consultez leurs documents: https://coverage.readthedocs.io/en/coverage-4.5.1/cmd.html#reporting

18
fips

Il est un peu difficile d'analyser vos expériences et vous n'avez pas inclus les lignes de commande que vous avez utilisées avec chaque expérience. Mais: si vous exécutez les tests avec:

python -m py.test test.py

vous pouvez ensuite les exécuter sous coverage.py avec:

coverage run -m py.test test.py
10
Ned Batchelder