En un módulo, tengo dos pruebas:
@pytest.fixture def myfixture(request): prepare_stuff() yield 1 clean_stuff() # time.sleep(10) # in doubt, I tried that, did not help def test_1(myfixture): a = somecode() assert a==1 def test_2(myfixture): b = somecode() assert b==1Cuando estas dos pruebas se ejecutan individualmente, todo está bien, es decir, ambas
pytest ./test_module.py:test_1e inmediatamente después:
pytest ./test_module.py:test_2ejecutar hasta completar y aprobar con éxito.
Pero:
pytest ./test_module.py -k "test_1 or test_2"informes:
collected 2 items test_module.py . y se cuelga para siempre (después de la investigación: test_1 se completó con éxito, pero la segunda llamada a prepare_stuff cuelga).
En mi configuración específica prepare_stuff , clean_stuff y somecode están bastante evolucionados, es decir, crean y eliminan algunos segmentos de memoria compartida, que cuando se hace mal puede resultar en algunos bloqueos. Así que algún problema aquí es posible.
Pero mi pregunta es: ¿hay cosas que ocurren entre dos llamadas de pytest (caso 1) que no ocurren entre la llamada de test_1 y test_2 del mismo "proceso de pytest" (caso 2), lo que podría explicar por qué funciona el "caso 1"? ¿Está bien mientras el "caso 2" se cuelga entre test_1 y test_2 ? Si es así, ¿hay alguna manera de "forzar" que ocurra la misma "limpieza" entre test_1 y test_2 para el "caso 2"?
Nota: ya intenté especificar el alcance de "myfixture" en "función", y también verifiqué dos veces que "clean_stuff" se llama después de "test_1", incluso en el "caso 2".
La estructura actual de myfixture cleanup() se llama entre test_1 y test_2 , a menos que prepare_stuff() una excepción no controlada. Probablemente notará esto, por lo que el problema más probable es que cleanup() no "limpia" todo lo que hizo prepare_stuff() , por lo que prepare_stuff() no puede configurar algo nuevamente.
En cuanto a su pregunta, no hay nada relacionado con pytest que pueda causar el bloqueo entre las pruebas. Puede forzar la llamada a cleanup() (incluso si se genera una excepción) agregando finalizador , se llamará después de la parte de desmontaje
@pytest.fixture def myfixture(request): request.addfinalizer(cleanup) prepare_stuff() yield 1Es probable que algo esté sucediendo en sus prepare_stuff y/o clean_stuff . Cuando ejecuta pruebas como:
pytest ./test_module.py -k "test_1 or test_2"
se ejecutan en el mismo contexto de ejecución, el mismo proceso, etc. Por lo tanto, si, por ejemplo, clean_stuff no realiza una limpieza adecuada, la ejecución de la siguiente prueba puede fallar. Cuando ejecuta pruebas como:
pytest ./test_module.py:test_1 pytest ./test_module.py:test_2 se ejecutan en diferentes contextos de ejecución, es decir, comienzan en un entorno absolutamente limpio y, a menos que esté modificando algunos recursos externos, puede eliminar fácilmente clean_stuff en este caso y pasarán de todos modos.
Para descartar el problema de pytest , simplemente intente ejecutar:
prepare_stuff() a = somecode() assert a==1 clean_stuff() prepare_stuff() b = somecode() assert b==1 clean_stuff() Estoy bastante seguro de que tendrá el mismo problema, lo que confirmaría que el problema está en su código, pero no en el pytest .
Tiene que ser algo en prepare_stuff , clean_stuff o somecode porque si reemplaza esos métodos por código ficticio, ¡funciona!
def prepare_stuff(): logging.warning("prepare_stuff()") def clean_stuff(): logging.warning("clean_stuff()") def somecode(): logging.warning("somecode()") return 0 /tmp/tmp.JOfTxVUv1z via 🐍 v3.8.10 (.env) ❯ pytest ./test_module.py -k "test_1 or test_2" ============================= test session starts ============================== platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: /tmp/tmp.JOfTxVUv1z collected 2 items test_module.py FF [100%] =================================== FAILURES =================================== ____________________________________ test_1 ____________________________________ myfixture = 1 def test_1(myfixture): a = somecode() > assert a==1 E assert 0 == 1 test_module.py:25: AssertionError ------------------------------ Captured log setup ------------------------------ WARNING root:test_module.py:5 prepare_stuff() ------------------------------ Captured log call ------------------------------- WARNING root:test_module.py:13 somecode() ---------------------------- Captured log teardown ----------------------------- WARNING root:test_module.py:9 clean_stuff() ____________________________________ test_2 ____________________________________ myfixture = 1 def test_2(myfixture): b = somecode() > assert b==1 E assert 0 == 1 test_module.py:29: AssertionError ------------------------------ Captured log setup ------------------------------ WARNING root:test_module.py:5 prepare_stuff() ------------------------------ Captured log call ------------------------------- WARNING root:test_module.py:13 somecode() ---------------------------- Captured log teardown ----------------------------- WARNING root:test_module.py:9 clean_stuff() =========================== short test summary info ============================ FAILED test_module.py::test_1 - assert 0 == 1 FAILED test_module.py::test_2 - assert 0 == 1 ============================== 2 failed in 0.03s =============================== /tmp/tmp.JOfTxVUv1z via 🐍 v3.8.10 (.env)