python unit-testing testing py.test

python - ¿Cómo afirmar correctamente que una excepción se plantea en Pytest?



unit-testing testing (6)

¿Has intentado eliminar "pytrace = True"?

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

¿Has intentado correr con ''--fulltrace''?

Código:

# coding=utf-8 import pytest def whatever(): return 9/0 def test_whatever(): try: whatever() except ZeroDivisionError as exc: pytest.fail(exc, pytrace=True)

Salida:

================================ 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 ==============================

¿Cómo hacer la trazabilidad de impresión más pequeña, para ver en qué parte de la función se generó una excepción?


Hay dos formas de manejar este tipo de casos en Pytest:

  • Usando la función pytest.raises

  • Usando el decorador de pytest.mark.xfail

Uso de pytest.raises :

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

Uso de pytest.mark.xfail :

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

Salida de 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/ukpdl, inifile: collected 1 item test_fun.py::test_whatever PASSED ======================== 1 passed in 0.01 seconds =============================

Salida del marcador pytest.xfail :

============================= 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/ukpdl, inifile: collected 1 item test_fun.py::test_whatever xfail ======================== 1 xfailed in 0.03 seconds=============================

Como dice el documento:

El uso de pytest.raises es probable que sea mejor para los casos en los que está probando excepciones que su propio código está aumentando deliberadamente, mientras que el uso de @pytest.mark.xfail con una función de verificación es probablemente mejor para algo como documentar errores no corregidos (donde la prueba describe "Debería" suceder) o errores en dependencias.


Mejor práctica será usar una clase que herede unittest.TestCase y running self.assertRaises.

Por ejemplo:

import unittest def whatever(): return 9/0 class TestWhatEver(unittest.TestCase): def test_whatever(): with self.assertRaises(ZeroDivisionError): whatever()

Entonces lo ejecutarías ejecutando:

pytest -vs test_path


Te refieres a algo como esto:

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


puedes probar

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


pytest.raises(Exception) es lo que necesitas.

Código

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

Salida

============================================================================================= 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 ======================================================================================

Tenga en cuenta que e_info guarda el objeto de excepción para que pueda extraer detalles de él. Por ejemplo, si desea verificar la pila de llamadas de excepción u otra excepción anidada dentro.