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 decorar dinámicamente una clase de pruebas de Python con múltiples parches

Se define una función en source.py y se llama en use_source.py. Lo aplico desde test.py de la siguiente manera:

source.py

def ejemplo_funcion():
    print("No quiero que esto se ejecute")

use_source.py

from source import ejemplo_funcion

def llamar_ejemplo_funcion():
    ejemplo_funcion()

test.py

import unittest
from unittest.mock import patch
import use_source

file_names = ["use_source.ejemplo_funcion"]


def funcion_falsa():
    print("Quiero que esto se ejecute en su lugar")


@patch(file_names[0], new=funcion_falsa)
class TestEjemplo(unittest.TestCase):

    def test_ejemplo(self):
        use_source.llamar_ejemplo_funcion()


if __name__ == '__main__':
    unittest.main()

Sin embargo, tengo varios archivos como use_source.py que deseo modificar, así que aquí está mi pregunta:

¿Cómo puedo llamar dinámicamente al decorador patch dado una lista de objetivos?

Estoy buscando algo como esto:

@patch_list(file_names, new=funcion_falsa)
class TestEjemplo(unittest.TestCase):

Podría hacer esto, pero tengo un número alto y variable de archivos para modificar:

@patch(file_names[0], new=funcion_falsa)
@patch(file_names[1], new=funcion_falsa)
class TestEjemplo(unittest.TestCase):

Por último, busco una solución que solo modifique test.py.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una posible solución es utilizar un bucle para aplicar dinámicamente el decorador patch a cada destino en la lista. Aquí tienes un ejemplo de implementación:

    import unittest
    from unittest.mock import patch
    import use_source
    
    file_names = ["use_source.example_function", "other_module.some_function", "..."]  # lista de destinos para parchear
    
    
    def fake_function():
        print("Quiero que esto se ejecute en su lugar")
    
    
    # Definimos dinámicamente un nuevo decorador que aplica patch a cada destino en la lista
    def patch_list(*targets, **kwargs):
        def decorator(test_case):
            for target in targets:
                test_case = patch(target, **kwargs)(test_case)
            return test_case
        return decorator
    
    
    # Aplicamos el decorador patch_list a la clase ExampleTest
    @patch_list(*file_names, new=fake_function)
    class ExampleTest(unittest.TestCase):
    
        def test_example(self):
            use_source.call_example_function()
    
    
    if __name__ == '__main__':
        unittest.main()
    

    En esta implementación, definimos una nueva función decoradora llamada patch_list que toma un número variable de argumentos (*targets) que representan la lista de destinos a ser parcheados. Luego, definimos un segundo nivel de decorador que aplica patch a cada destino en la lista utilizando *targets y **kwargs (que incluye la nueva función fake_function). Finalmente, aplicamos el decorador patch_list a la clase ExampleTest pasando la lista de nombres de archivos como argumentos (@patch_list(*file_names, new=fake_function)).

    Esta implementación permite parchear un número dinámico de destinos y solo requiere modificación en el archivo test.py.

Comments are closed.