it-swarm.com.de

Wie kann man richtig behaupten, dass eine Ausnahme in pytest ausgelöst wird?

Code:

# coding=utf-8
import pytest


def whatever():
    return 9/0

def test_whatever():
    try:
        whatever()
    except ZeroDivisionError as exc:
        pytest.fail(exc, pytrace=True)

Ausgabe:

================================ test session starts =================================
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
plugins: Django, cov
collected 1 items 

pytest_test.py F

====================================== FAILURES ======================================
___________________________________ test_whatever ____________________________________

    def test_whatever():
        try:
            whatever()
        except ZeroDivisionError as exc:
>           pytest.fail(exc, pytrace=True)
E           Failed: integer division or modulo by zero

pytest_test.py:12: Failed
============================== 1 failed in 1.16 seconds ==============================

Wie mache ich pytest print traceback, so würde ich sehen, wo in der whatever-Funktion eine Ausnahme ausgelöst wurde?

165
Gill Bates

pytest.raises(Exception) ist was Sie brauchen.

Code

import pytest

def test_passes():
    with pytest.raises(Exception) as e_info:
        x = 1 / 0

def test_passes_without_info():
    with pytest.raises(Exception):
        x = 1 / 0

def test_fails():
    with pytest.raises(Exception) as e_info:
        x = 1 / 1

def test_fails_without_info():
    with pytest.raises(Exception):
        x = 1 / 1

# Don't do this. Assertions are caught as exceptions.
def test_passes_but_should_not():
    try:
        x = 1 / 1
        assert False
    except Exception:
        assert True

# Even if the appropriate exception is caught, it is bad style,
# because the test result is less informative
# than it would be with pytest.raises(e)
# (it just says pass or fail.)

def test_passes_but_bad_style():
    try:
        x = 1 / 0
        assert False
    except ZeroDivisionError:
        assert True

def test_fails_but_bad_style():
    try:
        x = 1 / 1
        assert False
    except ZeroDivisionError:
        assert True

Ausgabe

============================================================================================= test session starts ==============================================================================================
platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4
collected 7 items 

test.py ..FF..F

=================================================================================================== FAILURES ===================================================================================================
__________________________________________________________________________________________________ test_fails __________________________________________________________________________________________________

    def test_fails():
        with pytest.raises(Exception) as e_info:
>           x = 1 / 1
E           Failed: DID NOT RAISE

test.py:13: Failed
___________________________________________________________________________________________ test_fails_without_info ____________________________________________________________________________________________

    def test_fails_without_info():
        with pytest.raises(Exception):
>           x = 1 / 1
E           Failed: DID NOT RAISE

test.py:17: Failed
___________________________________________________________________________________________ test_fails_but_bad_style ___________________________________________________________________________________________

    def test_fails_but_bad_style():
        try:
            x = 1 / 1
>           assert False
E           assert False

test.py:43: AssertionError
====================================================================================== 3 failed, 4 passed in 0.02 seconds ======================================================================================

Beachten Sie, dass e_info das Ausnahmeobjekt speichert, damit Sie Details daraus extrahieren können. Zum Beispiel, wenn Sie den Ausnahme-Aufrufstack oder eine andere verschachtelte Ausnahme darin prüfen möchten. 

193

Meinst du so etwas:

def test_raises():
    with pytest.raises(Exception) as excinfo:   
        raise Exception('some info')   
    assert excinfo.value.message == 'some info' 
88
simpleranchero

Es gibt zwei Möglichkeiten, um diese Art von Fällen in pytest zu behandeln:

  • pytest.raises-Funktion verwenden 

  • pytest.mark.xfail decorator verwenden

Verwendung von pytest.raises:

def whatever():
    return 9/0
def test_whatever():
    with pytest.raises(ZeroDivisionError):
        whatever()

Verwendung von pytest.mark.xfail:

@pytest.mark.xfail(raises=ZeroDivisionError)
def test_whatever():
    whatever()

Ausgabe von pytest.raises:

============================= test session starts ============================
platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- 
/usr/local/python_2.7_10/bin/python
cachedir: .cache
rootdir: /home/user, inifile:
collected 1 item

test_fun.py::test_whatever PASSED


======================== 1 passed in 0.01 seconds =============================

Ausgabe des pytest.xfail-Markers:

============================= test session starts ============================
platform linux2 -- Python 2.7.10, pytest-3.2.3, py-1.4.34, pluggy-0.4.0 -- 
/usr/local/python_2.7_10/bin/python
cachedir: .cache
rootdir: /home/user, inifile:
collected 1 item

test_fun.py::test_whatever xfail

======================== 1 xfailed in 0.03 seconds=============================

Wie die Dokumentation sagt:

Die Verwendung von pytest.raises ist wahrscheinlich in Fällen, in denen Sie Ausnahmen testen, die Ihr eigener Code absichtlich erhöht, wahrscheinlich besser, während die Verwendung von @pytest.mark.xfail mit einer Überprüfungsfunktion wahrscheinlich besser geeignet ist, um etwa nicht fixierte Fehler zu dokumentieren (wenn der Test beschreibt, was „passieren soll“) oder Fehler in Abhängigkeiten.

33

du kannst es versuchen

def test_exception():
    with pytest.raises(Exception) as excinfo:   
        function_that_raises_exception()   
    assert str(excinfo.value) == 'some info' 
30
d_j

pytest entwickelt sich ständig weiter und mit einer der netten Änderungen in der jüngsten Vergangenheit ist es jetzt möglich, gleichzeitig zu testen

  • der Ausnahmetyp (strenger Test)
  • die Fehlermeldung (strenge oder lose Prüfung mit einem regulären Ausdruck)

Zwei Beispiele aus der Dokumentation:

with pytest.raises(ValueError, match='must be 0 or None'):
    raise ValueError('value must be 0 or None')
with pytest.raises(ValueError, match=r'must be \d+$'):
    raise ValueError('value must be 42')

Ich habe diesen Ansatz in einer Reihe von Projekten verwendet und mag ihn sehr.

4

Diese Lösung verwenden wir: 

def test_date_invalidformat():
    """
    Test if input incorrect data will raises ValueError exception
    """
    date = "06/21/2018 00:00:00"
    with pytest.raises(ValueError):
        app.func(date) #my function to be tested

Bitte beziehen Sie sich auf pytest, http://pytest.readthedocs.io/de/reorganize-docs/assert.html#assert

3
SMDC

Der richtige Weg ist pytest.raises, aber ich habe in den Kommentaren hier einen interessanten alternativen Weg gefunden und möchte ihn für zukünftige Leser dieser Frage speichern:

try:
    thing_that_rasises_typeerror()
    assert False
except TypeError:
    assert True
3
Alexey Shrub

Haben Sie versucht, "pytrace = True" zu entfernen?

pytest.fail(exc, pytrace=True) # before
pytest.fail(exc) # after

Haben Sie versucht, mit --fulltrace zu laufen?

0
Loic Pantou

Besser praktizieren Sie eine Klasse, die unittest.TestCase erbt und self.assertRaises ausführt.

Zum Beispiel:

import unittest


def whatever():
    return 9/0


class TestWhatEver(unittest.TestCase):

    def test_whatever():
        with self.assertRaises(ZeroDivisionError):
            whatever()

Dann würden Sie es ausführen, indem Sie Folgendes ausführen:

pytest -vs test_path
0
kerbelp