python3 - ¿Cómo parchear las funciones internas de un módulo con simulacro?
funcion ord python (4)
Estoy bastante seguro de que su problema es que está importando ''mymodule'' dentro de sus funciones de prueba y, por lo tanto, el decorador de parches no tiene ninguna posibilidad de aplicar parches. Realice la importación en la parte superior del módulo, como cualquier otra importación.
Por "función interna", me refiero a una función que se llama desde dentro del mismo módulo en el que se define.
Estoy usando la biblioteca mock , específicamente los decoradores de patch , en mis pruebas de unidad. Son pruebas unitarias de Django, pero esto debería aplicarse a cualquier prueba de Python.
Tengo un módulo con varias funciones, muchas de las cuales se llaman entre sí. Por ejemplo (código ficticio, ignora la falta de decimal.Decimal):
TAX_LOCATION = ''StateName, United States''
def add_tax(price, user):
tax = 0
if TAX_LOCATION == ''StateName, UnitedStates'':
tax = price * .75
return (tax, price+tax)
def build_cart(...):
# build a cart object for `user`
tax, price = add_tax(cart.total, cart.user)
return cart
Estos son parte de una cadena de llamadas más profunda (func1 -> func2 -> build_cart -> add_tax), todos los cuales están en el mismo módulo.
En mis pruebas de unidad, me gustaría desactivar los impuestos para obtener resultados consistentes. Como lo veo, mis dos opciones son 1) parchear TAX_LOCATION (con una cadena vacía, por ejemplo) para que add_tax no haga nada o 2) parchear add_tax para devolver simplemente (0, precio).
Sin embargo, cuando intento parchear cualquiera de estos parches, el parche parece funcionar externamente (puedo importar la parte parcheada dentro de la prueba e imprimirla, obteniendo los valores esperados), pero parece no tener ningún efecto interno (los resultados que obtengo de la el código se comporta como si no se aplicara el parche).
Mis pruebas son así (de nuevo, código ficticio):
from mock import patch
from django.test import TestCase
class MyTests(TestCase):
@patch(''mymodule.TAX_LOCATION'', '''')
def test_tax_location(self):
import mymodule
print mymodule.TAX_LOCATION # ''''
mymodule.func1()
self.assertEqual(cart.total, original_price) # fails, tax applied
@patch(''mymodule.add_tax'', lambda p, u: (0, p))
def test_tax_location(self):
import mymodule
print mymodule.add_tax(50, None) # (0, 50)
mymodule.func1()
self.assertEqual(cart.total, original_price) # fails, tax applied
¿Alguien sabe si es posible que el simulacro parche las funciones que se usan internamente de esta manera, o estoy sin suerte?
La respuesta: limpiar sus malditas importaciones.
@patch(''mymodule.TAX_LOCATION'', '''')
efectivamente @patch(''mymodule.TAX_LOCATION'', '''')
cosas de manera apropiada, pero dado que nuestras importaciones en ese momento eran muy desordenadas - a veces mymodule.build_cart
, a veces mymodule.build_cart
project.mymodule.build_cart
- instancias de La importación "completa" no se parchó en absoluto. No podía esperarse que Mock supiera acerca de las dos rutas de importación separadas ... sin que se le indique explícitamente, de todos modos.
Desde entonces, hemos estandarizado todas nuestras importaciones en el camino más largo, y las cosas se comportan mucho mejor ahora.
Me gustaría añadir una solución distinta a la aceptada. También puede parchear el módulo antes de que se haya importado en otros módulos y eliminar el parche al final de su caso de prueba.
#import some modules that don''t use module you are going to patch
import unittest
from mock import patch
import json
import logging
...
patcher = patch(''some.module.path.function'', lambda x: x)
patcher.start()
import some.module.path
class ViewGetTests(unittest.TestCase):
@classmethod
def tearDownClass(cls):
patcher.stop()
Otra opción es llamar explícitamente a patch en la función:
mock.patch(''function_name'')
y para admitir la ejecución directa o desde py.test, etc.
mock.patch(__name__ + ''.'' + ''function_name'')