¿cómo patchear en Python?

publicado en: Articles | 0

¿qué es (monkey-)patching en Python?

(monkey-) patching es una técnica para cambiar el comportamiento del código sin alterar su fuente. Se realiza en tiempo de ejecución, Generalmente sobreescribiendo atributos de objetos existentes. Un objeto puede ser una instancia de algún tipo, una clase o incluso un módulo. La técnica se utiliza más comúnmente (ab) para las pruebas cuando no podemos pasar las burlas de una manera simple.

otro ejemplo impresionante es la biblioteca gevent que convierte el código síncrono en asíncrono mediante el uso de monkey-patching.,

comparémoslo usando wrk:

Gevent hizo que las solicitudes fueran una biblioteca amigable con la corrutina y gracias a la concurrencia, permitió que nuestro servidor de ejemplo manejara más de 13.5 veces más solicitudes por segundo.

al final, tenemos un programa que tiene una concurrencia basada en la corrutina (el mismo principio que en asyncio o node.js) pero su código todavía se ve como uno síncrono. No necesitamos bibliotecas cooperativas especiales o palabras clave async/await en nuestro código. Es casi como magia.

Patch in tests

Python incluye una utilidad para parchear, es decir, unittest.burla.parche., La forma predeterminada de usarlo es decorar nuestra función de prueba. Supongamos que tenemos una vista Django que se parece a esta<

y nos gustaría probarlo. Notamos que tiene una dependencia-ApiClient de otro módulo. Si queremos probar la vista get_stats de una manera predecible y confiable, necesitamos usar un test-double en lugar de ApiClient. Sin embargo, no hay una manera sencilla de hacerlo. Si fue pasado a get_stats como argumento, podríamos simplemente pasar Mock en su lugar.,

1
2
3
4

def get_stats(solicitud, api_client_class):
api_client = api_client_class()
…,

…pero ese no es el caso. Sin embargo, todavía podemos usar el decorador de parches.

esto no termina todavía, pero si ponemos un depurador en la prueba, notamos que ApiClient.get_stats_for es ahora un MagicMock:

significa que nuestra burla fue exitosa. Reemplazamos una dependencia problemática con un simulacro. Por cierto, si buscas las mejores prácticas para usar burlas, echa un vistazo a mi guía (casi) definitiva sobre la burla en Python o por qué la burla puede ser peligrosa cuando se usa en exceso.,

ahora, la prueba aún falla porque get_stats recibe un MagicMock mientras espera un diccionario. Tenemos que parametrizar el simulacro. Podemos hacerlo pasando un segundo argumento a @patch:

Patch sin decorador

patch también se puede usar como administrador de contexto. Un resultado de retorno será un simulacro que se inserta en un lugar de un atributo que se está parcheando:

» Python patch doesn’t work!»– cómo hacerlo bien?

a veces se enfrentará a la situación cuando a pesar de la presencia de patch decorator o context manager, la dependencia se verá como si no estuviera parcheada en absoluto., En resumen, puede ser porque hay múltiples referencias existentes a la cosa que está tratando de parchear. El código bajo prueba usa uno, pero usted parcheó con éxito otro. La operación fue exitosa, pero el paciente murió. Qué hacer?

En resumen, debe asegurarse de parchear la misma referencia que usa el código bajo prueba.

vea la sección Dónde parchear de unittest.mock documentation para más detalles. Alternativamente, puede usar una alternativa ingeniosa a patch, que es patch.objeto.

parche.objeto-más sencillo para hacerlo bien

parche.,el objeto es muy fácil de usar: solo importa el objeto cuyo atributo desea patch y aplica patch.objeto:

Si desea utilizar el parche.objeto para un método, importa una clase. Si quieres parchear.object a function or entire class, import the module they live in.

¿debería parchear?

(mono-) los parches se deben usar con moderación. Ese debería ser tu último recurso. En mi código, no tengo otra opción que patch gracias a la inyección de dependencias.

en el precio a largo plazo para tales trucos es muy, muy alto., Parchear a menudo significa tocar y cambiar los detalles de la implementación de una manera que no fue prevista por los autores. Esto introduce un acoplamiento adicional con cosas que no deberían tenerlo. Significa que serán más difíciles de cambiar.

si realmente tiene que hacerlo, parche solo API pública de Otra biblioteca o un módulo en su código.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *