web-dev-qa-db-fra.com

Comment obtenir que PyCharm affiche les diffs d'erreur entiers de pytest?

J'utilise Pycharm pour exécuter mes tests unitaires pytest . Je teste une API REST. Je dois donc souvent valider des blocs de JSON. Quand un test échoue, je vois quelque chose comme ceci:

FAILED
test_document_api.py:0 (test_create_documents)
{'items': [{'i...ages': 1, ...} != {'items': [{'...ages': 1, ...}

Expected :{'items': [{'...ages': 1, ...}
Actual   :{'items': [{'i...ages': 1, ...}
 <Click to see difference>

Lorsque je clique sur le lien "Cliquez pour voir la différence", la différence est en grande partie convertie en points d'ellipses, comme ci-dessous.

 Pycharm comparison with differences elided

C'est inutile car cela ne me montre pas ce qui est différent. J'obtiens ce comportement pour toute différence supérieure à une simple chaîne ou à un seul nombre.

Je suppose que Pycharm et/ou Pytest essaient d'éliminer les parties non informatives des différences pour les grandes sorties. Cependant, il est trop agressif ici et élit tout.

Comment faire en sorte que Pycharm et/ou pytest me montrent toute la différence?

J'ai essayé d'ajouter -vvv aux arguments supplémentaires de pytest, mais cela n'a aucun effet.


Depuis le message d'origine, j'ai vérifié que je voyais le même comportement lorsque j'exécutais des tests unitaires à partir de la ligne de commande. C’est donc un problème avec Pytest et non avec Pycharm.

Après avoir examiné les réponses que j’ai obtenues jusqu’à présent, je suppose que ce que je demande vraiment, c’est "est-il possible de définir maxDiff=None sans changer le code source de vos tests?" La lecture de pytest m'a donné l'impression que le commutateur -vv contrôle ce paramètre, mais cela ne semble pas être le cas.

13
W.P. McNeill

Si vous examinez de près les sources PyCharm , de la totalité de la sortie pytest, PyCharm utilise une seule ligne pour analyser les données à afficher dans la boîte de dialogue Click to see difference. Ceci est la ligne AssertionError: <message>:

def test_spam():
>       assert v1 == v2
E       AssertionError: assert {'foo': 'bar'} == {'foo': 'baz'}
E         Differing items:
E         {'foo': 'bar'} != {'foo': 'baz'}
E         Use -v to get the full diff

Si vous souhaitez voir la ligne de diff complète sans troncature, vous devez personnaliser cette ligne dans la sortie. Pour un seul test, cela peut être fait en ajoutant un message personnalisé à l'instruction assert:

def test_eggs():
    assert a == b, '{0} != {1}'.format(a, b)

Si vous souhaitez appliquer ce comportement à tous les tests, définissez custom pytest_assertrepr_compare hook. Dans le fichier conftest.py:

# conftest.py
def pytest_assertrepr_compare(config, op, left, right):
    if op in ('==', '!='):
        return ['{0} {1} {2}'.format(left, op, right)]

La comparaison d'égalité des valeurs sera toujours supprimée si elle est trop longue; pour afficher la ligne complète, vous devez toujours augmenter la verbosité avec l'indicateur -vv.

Maintenant, la comparaison d'égalité des valeurs dans la ligne AssertionError ne sera pas supprimée et le diff complet sera affiché dans la boîte de dialogue Click to see difference, mettant en évidence les parties diff:

 enter image description here

5
hoefling

Étant donné que pytest s’intègre à unittest, vous pouvez éventuellement le configurer en tant que test unittest, puis définir Test.maxDiff = None ou pour chaque test spécifique self.maxDiff = None

https://docs.pytest.org/fr/latest/index.html

Peut exécuter des suites sans tests (y compris les essais) et des suites de tests de nez;

Ceux-ci peuvent être utiles aussi ...

https://stackoverflow.com/a/21615720/9530790

https://stackoverflow.com/a/23617918/9530790

3
shmuels

Jetez un coup d’œil dans la base de code pytest et vous pourrez peut-être en essayer quelques-unes:

1) Définissez le niveau de verbosité dans l'exécution du test: 

./app_main --pytest --verbose test-suite/

2) Ajoutez la variable d’environnement pour "CI" ou "BUILD_NUMBER". Dans le lien vers Le fichier de troncature, vous pouvez voir que ces variables env sont utilisées pour Déterminer si le bloc de troncature est exécuté ou non.

import os

os.environ["BUILD_NUMBER"] = '1'
os.environ["CI"] = 'CI_BUILD'

3) Essayez de définir DEFAULT_MAX_LINES et DEFAULT_MAX_CHARS sur le module tronqué ( Je ne le recommande pas car il utilise un module privé ):

from _pytest.assertion import truncate

truncate.DEFAULT_MAX_CHARS = 1000
truncate.DEFAULT_MAX_LINES = 1000

Selon le code, l'option -vv devrait fonctionner, donc c'est étrange que ce ne soit pas pour vous:

Le comportement par défaut actuel consiste à tronquer les explications d'assertion sur ~ 8 lignes de terminaux, sauf si elles sont exécutées en mode "-vv" ou sur CI.

Fichier de troncature Pytest qui sont ce que je base mes réponses de: pytest/truncate.py

J'espère que quelque chose vous aide!

0
cullzie