I'm trying to test a many-to-many relationship between two Django models using factory_boy. The factory_boy documentation doesn't appear to discuss this and I'm having trouble figuring out what I'm doing wrong. When I run the first test, I get the error "AttributeError: 'Pizza' object has no attribute 'topping'". I get a similar error for the second test.
When I run the tests in the debugger, I can see a 'toppings' object but it don't understand how to get the name from it. Have I defined PizzaFactory's _prepare method properly? How do you access the name in one table from the other table when you have a many-to-many relationship?
Thanks.
models.py:
from django.db import models
class Topping(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Pizza(models.Model):
name = models.CharField(max_length=100)
toppings = models.ManyToManyField(Topping)
def __unicode__(self):
return self.name
factories.py:
import factory
from models import Topping, Pizza
class ToppingFactory(factory.Factory):
name = 'mushrooms'
class PizzaFactory(factory.Factory):
name = 'Vegetarian'
@classmethod
def _prepare(cls, create, **kwargs):
topping = ToppingFactory()
pizza = super(PizzaFactory, cls)._prepare(create, **kwargs)
pizza.toppings.add(topping)
return pizza
tests.py
from django.test import TestCase
import factory
from app.models import Topping, Pizza
from app.factories import ToppingFactory, PizzaFactory
class FactoryTestCase(TestCase):
def test_pizza_has_mushrooms(self):
pizza = PizzaFactory()
self.assertTrue(pizza.topping.name, 'mushrooms')
def test_mushrooms_on_pizza(self):
topping = ToppingFactory()
self.assertTrue(topping.pizza.name, 'Vegetarian')
mixer
... I was drawn tofactory_boy
initially. I liked how infactory_boy
, for a givenFactory
you could call a methodattributes()
and get adict
back, good for use withdataset
. But what's great aboutmixer
is it helps you be DRY because of how it can do so much on-the-fly. That means less testing-code to change if your code-under-test changes in the future! – Sorn