web-dev-qa-db-fra.com

Comment utiliser pytest pour vérifier que l'erreur n'est PAS déclenchée

Supposons que nous ayons un smth comme ça:

import py, pytest

ERROR1 = ' --- Error : value < 5! ---'
ERROR2 = ' --- Error : value > 10! ---'

class MyError(Exception):
    def __init__(self, m):
        self.m = m

    def __str__(self):
        return self.m

def foo(i):
    if i < 5:
        raise MyError(ERROR1)
    Elif i > 10:
        raise MyError(ERROR2)
    return i


# ---------------------- TESTS -------------------------
def test_foo1():
    with pytest.raises(MyError) as e:
        foo(3)
    assert ERROR1 in str(e)

def test_foo2():
    with pytest.raises(MyError) as e:
        foo(11)
    assert ERROR2 in str(e)

def test_foo3():
        ....
        foo(7)
         ....

Q: Comment puis-je faire en sorte que test_foo3 () vérifie qu'aucune erreur MyError n'est déclenchée? Il est évident que je pourrais simplement tester:

def test_foo3():
    assert foo(7) == 7

mais je veux tester cela via pytest.raises (). Est-ce possible d'une façon ou d'une autre? Par exemple: dans un cas, cette fonction "foo" n'a aucune valeur de retour du tout,

def foo(i):
    if i < 5:
        raise MyError(ERROR1)
    Elif i > 10:
        raise MyError(ERROR2)

il pourrait être judicieux de tester de cette façon, à mon humble avis.

44
paraklet

Un test échouera s'il déclenche une exception exceptionnelle inattendue. Vous pouvez simplement appeler foo (7) et vous aurez testé qu'aucune MyError n'est levée. Donc, ce qui suit suffira:

def test_foo3():
    foo(7)

Si vous voulez être explicite et écrire une déclaration assert pour cela, vous pouvez faire:

def test_foo3():
    try:
        foo(7)
    except MyError:
        pytest.fail("Unexpected MyError ..")
85
Faruk Sahin

S'appuyer sur ce que Oisin a mentionné ..

Vous pouvez faire un simple not_raises fonction qui agit de façon similaire à raises de pytest:

from contextlib import contextmanager

@contextmanager
def not_raises(exception):
  try:
    yield
  except exception:
    raise pytest.fail("DID RAISE {0}".format(exception))

C'est très bien si vous voulez vous en tenir à avoir raises ayant un homologue et donc que vos tests soient plus lisibles. Essentiellement, cependant, vous n'avez vraiment besoin de rien d'autre que d'exécuter le bloc de code que vous souhaitez tester sur sa propre ligne - pytest échouera de toute façon dès que ce bloc déclenche une erreur.

12
Pithikos

J'étais curieux de voir si un not_raises fonctionnerait. Un test rapide de ceci est (test_notraises.py):

from contextlib import contextmanager

@contextmanager
def not_raises(ExpectedException):
    try:
        yield

    except ExpectedException, err:
        raise AssertionError(
            "Did raise exception {0} when it should not!".format(
                repr(ExpectedException)
            )
        )

    except Exception, err:
        raise AssertionError(
            "An unexpected exception {0} raised.".format(repr(err))
        )

def good_func():
    print "hello"


def bad_func():
    raise ValueError("BOOM!")


def ugly_func():
    raise IndexError("UNEXPECTED BOOM!")


def test_ok():
    with not_raises(ValueError):
        good_func()


def test_bad():
    with not_raises(ValueError):
        bad_func()


def test_ugly():
    with not_raises(ValueError):
        ugly_func()

Cela semble fonctionner. Cependant, je ne sais pas si cela se lit vraiment bien dans le test.

6
Oisin