¿Cómo puedo proporcionar un parámetro pytest no fijo con un decorador personalizado?
Tenemos pruebas unitarias que se ejecutan a través de Pytest, utilizando un decorador personalizado para iniciar un servidor de eco simulado gestionado por contexto antes de cada prueba, y proporcionar su dirección a la prueba como parámetro adicional. Esto funciona en Python 2.
Sin embargo, si intentamos ejecutarlas en Python 3, Pytest se queja de que no puede encontrar un accesorio que coincida con el nombre del parámetro adicional, y las pruebas fallan.
Nuestras pruebas se ven similares a esto:
@with_mock_url(‘?status=404&content=test&content-type=csv&’)
def test_file_not_found(self, url):
res_id = self._test_resource(url)[‘id’]
result = update_resource(None, res_id)
assert not result, result
self.assert_archival_error(‘Error de estado informado por el servidor: 404 Not Found’, res_id)
Con una función decoradora como esta:
from functools import wraps
def with_mock_url(url=”):
“””
Inicie un servidor MockEchoTestServer y llame a la función decorada con la dirección del servidor
agregada a url
.
“””
def decorator(func):
@wraps(func)
def decorated(*args, **kwargs):
with MockEchoTestServer().serve() as serveraddr:
return func(*(args + (‘%s/%s’ % (serveraddr, url),)), **kwargs)
return decorated
return decorator
En Python 2 esto funciona; el servidor simulado comienza, la prueba obtiene una URL similar a “http://localhost:1234/?status=404&content=test&content-type=csv”, y luego el simulacro se apaga después.
En Python 3, sin embargo, obtenemos un error, “fixture ‘url’ no encontrada”.
¿Quizás hay una manera de decirle a Python, “Este parámetro se suministra desde otro lugar y no necesita una función”? ¿O hay, quizás, una manera fácil de convertir esto en una función?
davy.ai
Parece que el problema es causado por los cambios en la forma en que Pytest maneja las fixtures entre Python 2 y Python 3. Específicamente, el parámetro adicional “url” no se reconoce como una fixture en Python 3 y, por lo tanto, no se puede encontrar.
Una posible solución sería convertir el decorador en una fixture. Esto se puede hacer definiendo una función de fixture que inicie MockEchoTestServer y devuelva la URL del servidor, que luego se puede pasar como parámetro a las funciones de prueba. La fixture se puede usar agregando el nombre del parámetro a la firma de la función de prueba, así:
Al usar la fixture de esta manera, Pytest iniciará automáticamente MockEchoTestServer antes de cada prueba que lo use y lo cerrará después.
Alternativamente, si no es factible convertir el decorador en una fixture, otra solución posible sería marcar el parámetro como “no fixture” mediante el marcador
nonfixture_param
de Pytest. Esto se puede agregar a la anotación del parámetro de esta manera:Al marcar el parámetro de esta manera, Pytest omitirá buscar una fixture con ese nombre y simplemente pasará el valor del parámetro tal como está a la función de prueba. Sin embargo, esta solución puede ser menos sólida y más difícil de mantener que usar una fixture.