Quiero asegurarme de que estoy probando Modelos/Objetos de forma aislada y no como un gran sistema.Cómo probar modelos en Django con claves externas
Si tengo un objeto de pedido y tiene claves externas para clientes, pagos, artículos de pedido, etc. y quiero probar la funcionalidad de pedido, necesito crear accesorios para todos esos datos relacionados, o crearlos en código. Creo que lo que realmente necesito hacer es burlarme de los otros elementos, pero no veo una solución fácil (o posible) para eso si estoy haciendo consultas en estos Foreign Keys.
Las soluciones comunes (accesorios) realmente no me dejan probar un objeto a la vez. Estoy seguro de que esto se debe en parte a que mi aplicación es manera sobre acoplado.
Estoy tratando de adoptar TDD como mi principal método de trabajo, pero la forma en que funcionan las cosas con Django, parece que se pueden ejecutar pruebas de unidad muy triviales, o estas pruebas de integración masiva.
[Editar] mejor ejemplo explícito y un poco más de humildad
Lo que quiero decir es que me parece para poder sólo para ejecutar pruebas unitarias triviales. He visto personas con módulos muy bien probados y granulares. Estoy seguro de que algo de esto se puede seguir hasta un diseño pobre.
Ejemplo:
que tiene un modelo de llamada Upsell que está vinculada a un modelo de producto. Luego tengo un modelo de Choices que son hijos de Upsell (¿quieres lo que está detrás de la puerta # 1, # 2, # 3).
El modelo Upsell tiene varios métodos que derivan elementos necesarios para representar la plantilla de sus elecciones. El más importante es que crea una URL para cada elección. Hace esto a través de la manipulación de cadenas, etc. Si quería probar el método Upsell.get_urls(), quiero que no dependa de los valores de las opciones en los dispositivos, y no quiero que dependa del valor de Producto en los accesorios.
Ahora llené el archivo db en el método setUp para las pruebas, y eso funciona bien con la forma en que Django rechaza la transacción cada vez, pero solo fuera de setUp y TearDown. Esto funciona bastante bien, excepto que algunos de los Modelos son bastante complejos de configurar, mientras que en realidad solo necesito obtener un atributo para ello.
No puedo darle un ejemplo de eso, ya que no puedo lograrlo, pero aquí está el tipo de cosas que estoy haciendo ahora. Básicamente ingresé un pedido completo, creé el experimento A/B al que estaba conectado, etc. Y eso sin contar Producto, Categorías, etc. todo configurado por accesorios. No es el trabajo extra lo que me preocupa, ya que ni siquiera puedo probar un objeto basado en la base de datos a la vez. Las pruebas a continuación son importantes, pero son pruebas de integración. Me gustaría crear algo así probando cada elemento por separado. Como usted señaló, tal vez no debería haber elegido un marco tan estrechamente relacionado con el DB. ¿Existe algún tipo de inyección de dependencia con algo como esto? (Más allá de mis pruebas, pero el código en sí, así)
class TestMultiSinglePaySwap(TestCase):
fixtures = ['/srv/asm/fixtures/alchemysites.json','/srv/asm/fixtures/catalog.json','/srv/asm/fixtures/checkout_smallset.json','/srv/asm/fixtures/order-test-fixture.json','/srv/asm/fixtures/offers.json']
def setUp(self):
self.o = Order()
self.sp = SiteProfile.objects.get(pk=1)
self.c = Customer.objects.get(pk=1)
signals.post_save.disconnect(order_email_first, sender=Order)
self.o.customer = self.c
p = Payment()
p.cc_number = '4444000011110000'
p.cc_exp_month = '12'
p.cc_type = 'V'
p.cc_exp_year = '2020'
p.cvv2 = '123'
p.save()
self.o.payment = p
self.o.site_profile = self.sp
self.o.save()
self.initial_items = []
self.main_kit = Product.objects.get(pk='MOA1000D6')
self.initial_items.append(self.main_kit)
self.o.add_item('MOA1000D6', 1, False)
self.item1 = Product.objects.get(pk='MOA1041A-6')
self.initial_items.append(self.item1)
self.o.add_item('MOA1041A-6', 1, False)
self.item2 = Product.objects.get(pk='MOA1015-6B')
self.initial_items.append(self.item2)
self.o.add_item('MOA1015-6B', 1, False)
self.item3 = Product.objects.get(pk='STP1001-6E')
self.initial_items.append(self.item3)
self.o.add_item('STP1001-6E', 1, False)
self.swap_item1 = Product.objects.get(pk='MOA1041A-1')
def test_single_pay_swap_wholeorder(self):
o = self.o
swap_all_skus(o)
post_swap_order = Order.objects.get(pk = o.id)
swapped_skus = ['MOA1000D','MOA1041A-1','MOA1015-1B','STP1001-1E']
order_items = post_swap_order.get_all_line_items()
self.assertEqual(order_items.count(), 4)
pr1 = Product()
pr1.sku = 'MOA1000D'
item = OrderItem.objects.get(order = o, sku = 'MOA1000D')
self.assertTrue(item.sku.sku == 'MOA1000D')
pr2 = Product()
pr2.sku = 'MOA1015-1B'
item = OrderItem.objects.get(order = o, sku = 'MOA1015-1B')
self.assertTrue(item.sku.sku == 'MOA1015-1B')
pr1 = Product()
pr1.sku = 'MOA1041A-1'
item = OrderItem.objects.get(order = o, sku = 'MOA1041A-1')
self.assertTrue(item.sku.sku == 'MOA1041A-1')
pr1 = Product()
pr1.sku = 'STP1001-1E'
item = OrderItem.objects.get(order = o, sku = 'STP1001-1E')
self.assertTrue(item.sku.sku == 'STP1001-1E')
Tenga en cuenta que nunca he utilizado realmente un marco Mock aunque he intentado. Así que también es posible que me esté perdiendo algo fundamentalmente aquí.
Creo que cuando dijiste "no hay distinción entre la clase de modelo de negocio y la clase de modelo de persistencia", das en el clavo. Django le brinda la opción de base de datos de prueba y eso es lo más parecido a la burla que podría esperarse (aunque podría haber un backend db "simulado" que solo aplicaría las restricciones que desee). Al menos ahora sé que no estoy buscando algo que ya esté escrito. – zenWeasel
También puede consultar el https://github.com/dcramer/mock-django de David Cramer. Por cierto, hay una bifurcación de la biblioteca simulada en github: https://github.com/yujiabe/mock (actualizado en junio) 2012) – Andrei
FWIW, he adoptado el consejo de saltar con Mock y mock-django y he logrado mucho de lo que estaba intentando hacer. La biblioteca Mock requiere un poco de aprendizaje sobre cómo usarla correctamente, pero ha valido la pena. Así que solo quería actualizar que esos dos consejos eran correctos sobre el dinero y 2-3 años después uso esos métodos todos los días para escribir pruebas unitarias no triviales. – zenWeasel