"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Burlarse de las clases de Python

Burlarse de las clases de Python

Publicado el 2024-11-03
Navegar:901

Mocking Python Classes

Ú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.

Solución

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

  1. target=ClassA: el objeto (normalmente una clase) cuyo atributo queremos parchear.
  2. atributo="__init__": el nombre del atributo que queremos parchear.
  3. return_value=Ninguno: reemplazando el método __init__ con una función que no hace nada

De esta manera podemos crear variables simuladas en nuestro aparato.
Leer más sobre patch.object

Consejos de prueba

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! :)

Declaración de liberación Este artículo se reproduce en: https://dev.to/chen_ashkenazi/mocking-python-classes-4h96?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

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