使用 factory_boy 数据填充特定数据库以进行测试
Populate Specific Database With factory_boy Data for testing
我有一个应用程序有一些非托管模型,这些模型来自不同数据库中的 table。
我已经为我的所有模型创建了工厂,并且在大多数情况下 factory_boy 工作正常 很棒!
我 运行 遇到的问题与在其中一个字段上使用管理器的特定非托管模型有关。
class DailyRoll(StaffModel):
id = models.IntegerField(db_column='ID', primary_key=True)
location_id = models.IntegerField(db_column='locationID')
grade = models.CharField(db_column='grade', max_length=10)
end_year = models.IntegerField(db_column='endYear')
run_date = models.DateField(db_column='runDate')
person_count = models.IntegerField(db_column='personCount')
contained_count = models.IntegerField(db_column='containedCount')
double_count = models.IntegerField(db_column='doubleCount')
aide_count = models.IntegerField(db_column='aideCount')
one_count = models.IntegerField(db_column='oneCount')
bi_count = models.IntegerField(db_column='biCount')
last_run_date = managers.DailyRollManager()
class Meta(object):
managed = False
db_table = '[DATA].[position_dailyRoll]'
经理长这样:
class DailyRollManager(models.Manager):
def get_queryset(self):
last_run_date = super().get_queryset().using('staff').last().run_date
return super().get_queryset().using('staff').filter(
run_date=last_run_date
)
我的 factory_boy 设置如下所示(目前它非常基础,因为我只是想让它工作):
class DailyRollFactory(factory.Factory):
class Meta:
model = staff.DailyRoll
id = 1
location_id = 1
grade = 1
end_year = 2019
run_date = factory.fuzzy.FuzzyDateTime(timezone.now())
person_count = 210
contained_count = 1
double_count = 2
aide_count = 3
one_count = 4
bi_count = 5
last_run_date = managers.DailyRollManager()
我确定 last_run_date 设置不正确 - 但我不知道如何最好地使用 factory_boy 中的管理器。
当我 运行 我的测试时 - 它会创建一个名为 'defaultdb' 的默认 sqlite3 数据库来针对 运行 测试(我们在生产中使用 SQL 服务器 - 但由于安全性我们不能让 django 控制 master 来管理测试)。为此,我必须创建一个解决方法,但它确实有效。
我的设置如下所示:
if 'test' in sys.argv or 'test_coverage' in sys.argv:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'defaultdb.sqlite3'),
},
'staff': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'staff.sqlite3'),
},
}
我的测试很简单:
def test_index_returns_200_and_correct_template(self):
"""
index page returns a 200
"""
# Load test data which index needs
# if this is not included the test fails with
# 'no such table: [DATA].[position_dailyRoll]'
f.DailyRollFactory()
response = self.client.get(reverse('position:index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'position/index.html')
如果我不在测试中包含 f.DailyRollFactory()
,它会失败并出现以下错误:
no such table: [DATA].[position_dailyRoll]
当我包含 f.DailyRollFactory()
时出现此错误:
TypeError: 'last_run_date' is an invalid keyword argument for this function
我认为最终该经理试图查看 'staff' 数据库 - 我正在创建该数据库,但它是空的并且不包含任何数据。
我在想办法:
A) 我怎样才能像工厂男孩模型中那样用数据预填充 staff
数据库?我 认为 可以解决我 运行 遇到的问题。会吗?我不确定。
B) 在 factory_boy 工厂,这是对付经理的正确方式吗?我不确定具体该如何处理。
我最终使用了 Pytest-Django
,因为该测试框架实际上允许做我想做的事情。
使用 --nomigrations
标志,它采用我的模型,这些模型在测试中仅由 django 管理,并在测试数据库。然后我可以使用 factory_boy
创建模拟数据并对其进行测试!
我有一个应用程序有一些非托管模型,这些模型来自不同数据库中的 table。
我已经为我的所有模型创建了工厂,并且在大多数情况下 factory_boy 工作正常 很棒!
我 运行 遇到的问题与在其中一个字段上使用管理器的特定非托管模型有关。
class DailyRoll(StaffModel):
id = models.IntegerField(db_column='ID', primary_key=True)
location_id = models.IntegerField(db_column='locationID')
grade = models.CharField(db_column='grade', max_length=10)
end_year = models.IntegerField(db_column='endYear')
run_date = models.DateField(db_column='runDate')
person_count = models.IntegerField(db_column='personCount')
contained_count = models.IntegerField(db_column='containedCount')
double_count = models.IntegerField(db_column='doubleCount')
aide_count = models.IntegerField(db_column='aideCount')
one_count = models.IntegerField(db_column='oneCount')
bi_count = models.IntegerField(db_column='biCount')
last_run_date = managers.DailyRollManager()
class Meta(object):
managed = False
db_table = '[DATA].[position_dailyRoll]'
经理长这样:
class DailyRollManager(models.Manager):
def get_queryset(self):
last_run_date = super().get_queryset().using('staff').last().run_date
return super().get_queryset().using('staff').filter(
run_date=last_run_date
)
我的 factory_boy 设置如下所示(目前它非常基础,因为我只是想让它工作):
class DailyRollFactory(factory.Factory):
class Meta:
model = staff.DailyRoll
id = 1
location_id = 1
grade = 1
end_year = 2019
run_date = factory.fuzzy.FuzzyDateTime(timezone.now())
person_count = 210
contained_count = 1
double_count = 2
aide_count = 3
one_count = 4
bi_count = 5
last_run_date = managers.DailyRollManager()
我确定 last_run_date 设置不正确 - 但我不知道如何最好地使用 factory_boy 中的管理器。
当我 运行 我的测试时 - 它会创建一个名为 'defaultdb' 的默认 sqlite3 数据库来针对 运行 测试(我们在生产中使用 SQL 服务器 - 但由于安全性我们不能让 django 控制 master 来管理测试)。为此,我必须创建一个解决方法,但它确实有效。
我的设置如下所示:
if 'test' in sys.argv or 'test_coverage' in sys.argv:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'defaultdb.sqlite3'),
},
'staff': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'staff.sqlite3'),
},
}
我的测试很简单:
def test_index_returns_200_and_correct_template(self):
"""
index page returns a 200
"""
# Load test data which index needs
# if this is not included the test fails with
# 'no such table: [DATA].[position_dailyRoll]'
f.DailyRollFactory()
response = self.client.get(reverse('position:index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'position/index.html')
如果我不在测试中包含 f.DailyRollFactory()
,它会失败并出现以下错误:
no such table: [DATA].[position_dailyRoll]
当我包含 f.DailyRollFactory()
时出现此错误:
TypeError: 'last_run_date' is an invalid keyword argument for this function
我认为最终该经理试图查看 'staff' 数据库 - 我正在创建该数据库,但它是空的并且不包含任何数据。
我在想办法:
A) 我怎样才能像工厂男孩模型中那样用数据预填充 staff
数据库?我 认为 可以解决我 运行 遇到的问题。会吗?我不确定。
B) 在 factory_boy 工厂,这是对付经理的正确方式吗?我不确定具体该如何处理。
我最终使用了 Pytest-Django
,因为该测试框架实际上允许做我想做的事情。
使用 --nomigrations
标志,它采用我的模型,这些模型在测试中仅由 django 管理,并在测试数据库。然后我可以使用 factory_boy
创建模拟数据并对其进行测试!