es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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?

Tags:  , , , ,

Answer

  1. Avatar for 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í:

    import pytest
    
    @pytest.fixture
    def mock_url():
        with MockEchoTestServer().serve() as serveraddr:
            yield serveraddr
    
    def test_file_not_found(mock_url):
        url = '?status=404&content=test&content-type=csv'
        res_id = self._test_resource('%s/%s' % (mock_url, url))['id']
        result = update_resource(None, res_id)
        assert not result, result
        self.assert_archival_error('Server reported status error: 404 Not Found', res_id)
    

    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:

    def test_file_not_found(url: pytest.nonfixture_param):
        ...
    

    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.

Comments are closed.