Últimamente, tuve que escribir pruebas unitarias usando Pytest para un módulo de Python. El módulo contiene una clase donde se inicializan otras clases dentro de su constructor.
Como de costumbre, creé un accesorio para esta clase para facilitar la escritura de una prueba para cada método de clase. En este punto me encontré con algunos problemas cuando intenté burlarme de las diferentes clases iniciadas en el constructor. La burla no funcionó y todavía se estaban creando instancias de estas clases.
Después de investigar un poco y combinar algunas soluciones diferentes que encontré en línea, quiero compartir cómo logré burlarme de las clases.
Aquí hay un ejemplo de la clase de la que intenté burlarme:
class ClassA: def __init__(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Queremos establecer un valor para cada campo de esta clase durante las pruebas. Este valor puede ser Ninguno o una clase simulada, pero no queremos iniciaciones de las clases ClassB y ClassC.
En nuestro caso, decidamos que self.class_b y self.class_c deben ser simulacros:
@pytest.fixture def mock_class_b(): class_b = Mock(spec=ClassB) return class_b @pytest.fixture def mock_class_c(): class_c = Mock(spec=ClassC) return class_c
Entonces, un elemento fijo para esta clase que sirve a nuestro objetivo se ve así:
@pytest.fixture def class_a_mock(mock_class_b, mock_class_c): with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init: class_a = ClassA() class_a.class_b = mock_class_b class_a.class_c = mock_class_c class_b.count = 0 return class_a
La parte importante es cómo usar la función patch.object, que proviene del módulo unittest.mock en Python. Se utiliza en pruebas para reemplazar temporalmente un atributo de un objeto determinado con un valor simulado u otro.
Argumentos
De esta manera podemos crear variables simuladas en nuestro aparato.
Leer más sobre patch.object
Escribí este tutorial para este tipo de casos en los que, por cualquier motivo, no podemos cambiar el código de la Clase A. Sin embargo, generalmente recomiendo modificar el código si es posible, no para cambiar la lógica, sino para hacerlo más comprobable. .
Aquí hay algunos ejemplos de cómo modificar la Clase A para hacerla más comprobable:
Opción 1: Pasar instancias de clase B y clase C como parámetros.
De esta manera, cuando escribimos el dispositivo, podemos pasar simulacros en lugar de instancias.
class ClassA: def __init__(self, class_b_instance, class_c_instance): self.class_b = class_b_instance self.class_c = class_c_instance self.count = 0
Opción 2: Crea una variable booleana que indica el modo de prueba.
De esta manera podemos decidir qué campos de la clase A obtendrán o no un valor cuando se inicie.
class ClassA: def __init__(self, test_mode=False): if not test_mode: self.class_b = ClassB() self.class_c = ClassC() self.count = 0
Opción 3: Realizar iniciaciones de clases en un método separado.
Este enfoque nos da la opción de evitar llamar a set_class_variables en el módulo de prueba.
class ClassA: def __init__(self): self.class_b = None self.class_c = None self.count = None def set_class_variables(self): self.class_b = ClassB() self.class_c = ClassC() self.count = 0
¡Espero que esto ayude! :)
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3