Estoy usando declaraciones de afirmación de Python para que coincida con el comportamiento real y esperado. No tengo control sobre estos, ya que si hay una prueba de error, aborta los casos. Quiero tomar el control del error de aserción y quiero definir si quiero abortar el caso de prueba en caso de fallo o no.
También quiero agregar algo como si hay un error de aserción, entonces el caso de prueba debe pausarse y el usuario puede reanudar en cualquier momento.
No tengo idea de cómo hacer esto
Ejemplo de código, estamos usando pytest aquí
import pytest
def test_abc():
a = 10
assert a == 10, "some error message"
Below is my expectation
Cuando afirmar arroja un aserción de error, debería tener la opción de pausar el caso de prueba y puedo depurar y luego reanudar. Para pausar y reanudar, usaré el módulo tkinter
. Haré una función de aserción como a continuación
import tkinter
import tkinter.messagebox
top = tkinter.Tk()
def _assertCustom(assert_statement, pause_on_fail = 0):
#assert_statement will be something like: assert a == 10, "Some error"
#pause_on_fail will be derived from global file where I can change it on runtime
if pause_on_fail == 1:
try:
eval(assert_statement)
except AssertionError as e:
tkinter.messagebox.showinfo(e)
eval (assert_statement)
#Above is to raise the assertion error again to fail the testcase
else:
eval (assert_statement)
En el futuro, tengo que cambiar cada declaración de aserción con esta función como
import pytest
def test_abc():
a = 10
# Suppose some code and below is the assert statement
_assertCustom("assert a == 10, 'error message'")
Este es un esfuerzo demasiado grande para mí, ya que tengo que hacer cambios en miles de lugares donde he usado la afirmación. ¿Hay alguna manera fácil de hacerlo en pytest
Summary:
Necesito algo donde pueda pausar el caso de prueba en caso de falla y luego reanudarlo después de la depuración. Sé acerca de tkinter
y esa es la razón por la que lo he usado. Cualquier otra idea será bienvenida
Note
: el código anterior aún no se ha probado. También puede haber pequeños errores de sintaxis
Editar: Gracias por las respuestas. Extendiendo esta pregunta un poco más adelante ahora. ¿Qué pasa si quiero cambiar el comportamiento de afirmar? Actualmente, cuando hay un error de aserción, sale el caso de prueba. ¿Qué pasa si quiero elegir si necesito salir de caso de prueba en caso de fallo de afirmación particular o no? No quiero escribir una función de aserción personalizada como se mencionó anteriormente porque de esta manera tengo que cambiar en varios lugares
3 respuestas
Si está utilizando PyCharm, puede agregar un punto de interrupción de excepción para pausar la ejecución cada vez que falla una aserción. Seleccione Ver puntos de interrupción (CTRL-SHIFT-F8) y agregue un controlador de excepción en aumento para AssertionError. Tenga en cuenta que esto puede ralentizar la ejecución de las pruebas.
De lo contrario, si no le importa detenerse al final de cada prueba fallida (justo antes de que se produzca un error) en lugar de en el momento en que la afirmación falla, entonces tiene algunas opciones. Sin embargo, tenga en cuenta que en este punto ya podrían haberse ejecutado varios códigos de limpieza, como el cierre de archivos que se abrieron en la prueba. Las opciones posibles son:
Puede decirle a pytest que lo coloque en el depurador de errores utilizando - opción pdb.
Puede definir el siguiente decorador y decorar cada función de prueba relevante con él. (Además de registrar un mensaje, también puede iniciar un pdb.post_mortem en este punto, o incluso un code.interact interactivo con los locales del marco donde se originó la excepción, como se describe en esta respuesta.)
from functools import wraps
def pause_on_assert(test_func):
@wraps(test_func)
def test_wrapper(*args, **kwargs):
try:
test_func(*args, **kwargs)
except AssertionError as e:
tkinter.messagebox.showinfo(e)
# re-raise exception to make the test fail
raise
return test_wrapper
@pause_on_assert
def test_abc()
a = 10
assert a == 2, "some error message"
- Si no desea decorar manualmente cada función de prueba, puede definir un dispositivo de uso automático que inspeccione sys.last_value:
import sys
@pytest.fixture(scope="function", autouse=True)
def pause_on_assert():
yield
if hasattr(sys, 'last_value') and isinstance(sys.last_value, AssertionError):
tkinter.messagebox.showinfo(sys.last_value)
Puede lograr exactamente lo que desea sin absolutamente ninguna modificación de código con pytest --pdb.
Con tu ejemplo:
import pytest
def test_abc():
a = 9
assert a == 10, "some error message"
Ejecutar con --pdb:
py.test --pdb
collected 1 item
test_abc.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def test_abc():
a = 9
> assert a == 10, "some error message"
E AssertionError: some error message
E assert 9 == 10
test_abc.py:4: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /private/tmp/a/test_abc.py(4)test_abc()
-> assert a == 10, "some error message"
(Pdb) p a
9
(Pdb)
Tan pronto como una prueba falla, puede depurarla con el depurador de python incorporado. Si ha terminado de depurar, puede continue
con el resto de las pruebas.
Una solución simple, si está dispuesto a usar Visual Studio Code, podría ser usar puntos de corte condicionales.
Esto le permitiría configurar sus afirmaciones, por ejemplo:
import pytest
def test_abc():
a = 10
assert a == 10, "some error message"
Luego agregue un punto de interrupción condicional en su línea de afirmación que solo se romperá cuando su afirmación falle: