我是Django的初学者,刚开始为我的项目做一些测试.我想要做的是用selenium构建一个功能测试,登录到Django Admin站点.
我首先按照本教程http://www.tdd-django-tutorial.com/tutorial/1/使用fixtures和dumpdata来为测试应用程序(创建新数据库)提供管理员帐户信息.这很好用.
然后我想看看我是否可以使用工厂男孩来替换灯具.工厂男孩通过在tests.py文件中实例化必要的对象来工作,这对我来说似乎更干净.不知怎的,我无法让这个工作,Factory_boy文档不太有用......
这是我的tests.py
from django.test import LiveServerTestCase
from django.contrib.auth.models import User
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import factory
class UserFactory(factory.Factory):
FACTORY_FOR = User
username = 'jeff'
password = 'pass'
is_superuser = True
class AdminTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
def tearDown(self):
self.browser.quit()
def test_if_admin_login_is_possible(self):
jeff = UserFactory.create()
# Jeff opens the browser and goes to the admin page
self.browser = webdriver.Firefox()
self.browser.get(self.live_server_url + '/admin/')
# Jeff sees the familiar 'Django Administration' …Run Code Online (Sandbox Code Playgroud) Factory_boy用于fake-factory (Faker)生成随机值,我想直接使用Faker在我的Django测试中生成一些随机值.
Factory_boy文档建议使用factory.Faker及其提供者:
class RandomUserFactory(factory.Factory):
class Meta:
model = models.User
first_name = factory.Faker('first_name')
Run Code Online (Sandbox Code Playgroud)
但这不会产生任何名称:
>>> import factory
>>> factory.Faker('name')
<factory.faker.Faker object at 0x7f1807bf5278>
>>> type(factory.Faker('name'))
<class 'factory.faker.Faker'>
Run Code Online (Sandbox Code Playgroud)
从factory_boy faker.py类factory.Faker('ean', length=10)调用,faker.Faker.ean(length=10)但Faker文档说它应该显示一个名称:
from faker import Faker
fake = Faker()
fake.name()
# 'Lucy Cechtelar'
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以使用Faker而不是直接设置实例Faker?
from faker import Factory
fake = Factory.create()
fake.name()
Run Code Online (Sandbox Code Playgroud) 我正在使用factory_boy来创建测试夹具.我有两个简单的工厂,由SQLAlchemy模型支持(简化如下).
我希望能够AddressFactory.create()多次调用,并且Country如果它还不存在则创建它,否则我希望它重新使用现有记录.
class CountryFactory(factory.Factory):
FACTORY_FOR = Country
cc = "US"
name = "United States"
class AddressFactory(factory.Factory):
FACTORY_FOR = Address
name = "Joe User"
city = "Seven Mile Beach"
country = factory.SubFactory(CountryFactory, cc="KY", name="Cayman Islands")
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何设置这些工厂,以便factory_boy每次创建地址时都不会尝试创建新的国家/地区?
代码:类StockFactory(UniqueObjectsFactory):FACTORY_FOR =股票FACTORY_DJANGO_GET_OR_CREATE =('name','market')
market = factory.SubFactory(MarketFactory)
symbol = FuzzyAttribute(lambda: ''.join(random.choice(string.ascii_uppercase) for _ in xrange(4)))
name = FuzzyCompanyName()
# last_trade_price = fuzzy.FuzzyDecimal(0.0, 10000.0)
class PositionsFactory(FreezeableFactory):
FACTORY_FOR = Position
FACTORY_DJANGO_GET_OR_CREATE = ('stock','AnotherObject')
id = FuzzyInteger(100000)
stock = factory.SubFactory(Stock)
AnotherObject = factory.SubFactory(AnotherObject) #If I comment stock out it would fail here
created_date = FuzzyDateTime(start_dt=datetime(2013, 1, 1, tzinfo=compat.UTC))
Run Code Online (Sandbox Code Playgroud)
错误:
File "/home/alon/Projects/stox-server/execution/tests/functional/test_positions.py", line 21, in setUp
PositionsFactory.create( portfolio=self.portfolio)
File "/home/alon/.virtualenvs/stox-server/local/lib/python2.7/site-packages/factory/base.py", line 522, in create
attrs = cls.attributes(create=True, extra=kwargs)
File "/home/alon/.virtualenvs/stox-server/local/lib/python2.7/site-packages/factory/base.py", line 365, in attributes
force_sequence=force_sequence, …Run Code Online (Sandbox Code Playgroud) 我正在使用Factory Boy为我的django应用程序创建测试工厂.我遇到问题的模型是一个非常基本的Account模型,它与django User auth模型有一个OneToOne关系(使用django <1.5):
# models.py
from django.contrib.auth.models import User
from django.db import models
class Account(models.Model):
user = models.OneToOneField(User)
currency = models.CharField(max_length=3, default='USD')
balance = models.CharField(max_length="5", default='0.00')
Run Code Online (Sandbox Code Playgroud)
这是我的工厂:
# factories.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
import factory
from models import Account
class AccountFactory(factory.django.DjangoModelFactory):
FACTORY_FOR = Account
user = factory.SubFactory('app.factories.UserFactory')
currency = 'USD'
balance = '50.00'
class UserFactory(factory.django.DjangoModelFactory):
FACTORY_FOR = User
username = 'bob'
account = factory.RelatedFactory(AccountFactory)
Run Code Online (Sandbox Code Playgroud)
因此,每当调用AccountFactory时,我都希望工厂男孩能够创建一个相关的UserFactory:
# tests.py
from django.test import TestCase
from …Run Code Online (Sandbox Code Playgroud) 我不明白为什么factory_boy比直接在Django测试中创建ORM /模型实例更受欢迎.factory_boy网站几乎无法解释使用它的好处.
作为固定装置的替代品是有意义的,这些固定装置难以管理,速度慢等.
但是,为什么不只是根据测试需要创建模型实例?
如果factory_boy完全取代了对db的写入,那么很好,我认为在这种情况下它会非常有用,但工厂男孩创建的django模型实例仍然与数据库交互.
另一个潜在的好处是对序列的支持,但是在不需要工厂男孩的情况下创建序列/样本数据并不困难.
总而言之,我看到使用工厂男孩几乎没有任何好处,直接创建对象/模型实例.
我希望我错过了一些明显的东西!
我正在尝试使用factory_boy测试两个Django模型之间的多对多关系.factory_boy文档似乎没有讨论这个问题,我无法弄清楚我做错了什么.当我运行第一个测试时,我得到错误"AttributeError:'Pizza'对象没有属性'顶部'".第二次测试我得到了类似的错误.
当我在调试器中运行测试时,我可以看到"浇头"对象,但它不知道如何从中获取名称.我是否正确定义了PizzaFactory的_prepare方法?当你有多对多的关系时,如何从另一个表中访问一个表中的名称?
谢谢.
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
from django.test import TestCase
import factory
from app.models import Topping, Pizza
from app.factories import ToppingFactory, PizzaFactory …Run Code Online (Sandbox Code Playgroud) 我factory.LazyAttribute在SubFactory调用中使用传入一个对象,在对象中创建factory_parent.这很好用.
但是,如果我将创建的对象传递给a RelatedFactory,LazyAttribute则无法再看到factory_parent并失败.
这很好用:
class OKFactory(factory.DjangoModelFactory):
class = Meta:
model = Foo
exclude = ['sub_object']
sub_object = factory.SubFactory(SubObjectFactory)
object = factory.SubFactory(ObjectFactory,
sub_object=factory.LazyAttribute(lambda obj: obj.factory_parent.sub_object))
Run Code Online (Sandbox Code Playgroud)
同样的呼叫在LazyAttribute这里失败:
class ProblemFactory(OKFactory):
class = Meta:
model = Foo
exclude = ['sub_object', 'object']
sub_object = factory.SubFactory(SubObjectFactory)
object = factory.SubFactory(ObjectFactory,
sub_object=factory.LazyAttribute(lambda obj: obj.factory_parent.sub_object))
another_object = factory.RelatedFactory(AnotherObjectFactory, 'foo', object=object)
Run Code Online (Sandbox Code Playgroud)
相同的LazyAttribute调用不能再看到factory_parent,并且只能访问AnotherObject值.LazyAttribute抛出错误:
AttributeError: The parameter sub_object is unknown. Evaluated attributes are...[then lists all …Run Code Online (Sandbox Code Playgroud) 我开始使用这个factory_boy包,所以我建立了一些工厂,并想测试创建的对象不会引发任何验证错误。
这是我正在使用的 mixin,它基本上从一个模块中获取每个工厂,创建一个实例,然后测试从.full_clean(). 加载的用户设备是 ID 为 1 到 10 的 10 个实例。
class FactoriesTestCaseMixin:
fixtures = [
'user/tests/fixtures/user.json',
]
module = None
def test_factories(self):
err_msg = '{name} caused errors:\n{errors}'
factories = [
(name, obj) for name, obj in inspect.getmembers(self.module, inspect.isclass)
if obj.__module__ == self.module.__name__
and not obj._meta.abstract
]
for factory in factories:
name = factory[0]
instance = factory[1]()
errors = None
try:
instance.full_clean()
except ValidationError as e:
errors = e
self.assertTrue(errors is None, err_msg.format(name=name, errors=errors))
Run Code Online (Sandbox Code Playgroud)
mixin …
我需要创建十个示例用户(User),每个用户必须有五十个文档(Doc).如何使用factoryboy在tests.py中执行此操作?
#factories.py
from app_name.models import *
import factory
from datetime import datetime, timedelta, time
from django.contrib.auth.models import User
class UserFactory(factory.Factory):
FACTORY_FOR = User
username = factory.Sequence(lambda n: 'User ' + n)
email = 'demo@mail.com'
password = '1234567'
class DocFactory(factory.Factory):
FACTORY_FOR = Doc
user = factory.SubFactory(UserFactory)
kategories = '1'
doc_number = '12345678'
date_join = factory.Sequence(lambda n:(datetime.now() + timedelta(days=n)).date(), int)
Run Code Online (Sandbox Code Playgroud)
在我的tests.py中:
from django.test import TestCase
from django_dynamic_fixture import G
from factories import *
Run Code Online (Sandbox Code Playgroud) factory-boy ×10
python ×8
django ×7
testing ×2
unit-testing ×2
factory ×1
faker ×1
selenium ×1
sqlalchemy ×1