18

factory_boy を使用して、2 つの Django モデル間の多対多の関係をテストしようとしています。factory_boy のドキュメントはこれについて議論していないようで、何が間違っているのかを理解するのに苦労しています。最初のテストを実行すると、「AttributeError: 'Pizza' object has no attribute 'topping'」というエラーが表示されます。2 番目のテストでも同様のエラーが発生します。

デバッガーでテストを実行すると、「トッピング」オブジェクトが表示されますが、そこから名前を取得する方法がわかりません。PizzaFactory の _prepare メソッドを正しく定義しましたか? 多対多の関係がある場合、あるテーブルの名前に他のテーブルからどのようにアクセスしますか?

ありがとう。

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

factory.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')
4

2 に答える 2

30

@factory.post_generationデコレータを使用する必要があると思います:

class PizzaFactory(factory.Factory):
    name = 'Vegetarian'

    @factory.post_generation
    def toppings(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        if extracted:
            # A list of groups were passed in, use them
            for topping in extracted:
                self.toppings.add(topping)

次に、tests.pyでそれを呼び出しますpizza = PizzaFactory.create(toppings=(topping1, topping2, tooping3))

https://factoryboy.readthedocs.org/en/latest/recipes.htmlから。

于 2013-11-20T10:41:52.770 に答える
6

代わりにミキサーを使用してください:

from mixer.backend.django import mixer

# Generate toppings randomly
pizza = mixer.blend(Pizza, toppings=mixer.RANDOM)

# Set toppings
toppings = mixer.cycle(3).blend(Topping)
pizza = mixer.blend(Pizza, toppings=toppings)

# Generate toppings with name=tomato
pizze = mixer.blend(Pizza, toppings__name='tomato')

簡単で、構成可能で、高速で、スキーマレスで、宣言型であり、必要なものをいくつかのテストで取得しています。

于 2014-04-30T12:24:09.150 に答える