【问题标题】:Populate Specific Database With factory_boy Data for testing使用 factory_boy 数据填充特定数据库以进行测试
【发布时间】:2018-09-06 12:43:44
【问题描述】:

我有一个应用程序,其中包含一些从不同数据库中的表中提取的非托管模型。

我已经为我的所有模型创建了工厂,并且在大多数情况下 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 Server——但由于安全性,我们无法让 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

我认为该经理最终会尝试查看“员工”数据库 - 我已创建该数据库,但它是空的并且不包含任何数据。

我想弄清楚:

A) 我如何使用我的工厂男孩模型中的数据预先填充 staff 数据库?我认为可能会解决我遇到的问题。会吗?我不确定。

B) 在 factory_boy 工厂中,这样处理经理是否正确?我不确定如何处理。

【问题讨论】:

    标签: python django django-testing django-tests factory-boy


    【解决方案1】:

    我最终使用了Pytest-Django,因为该测试框架实际上允许做我想做的事。

    使用--nomigrations 标志,它采用仅由django 在测试中管理的模型,并在测试数据库中为它们创建适当的表名(使用它们的db_table 属性)。然后我可以使用factory_boy 来创建模拟数据并进行测试!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-01
      • 2015-01-18
      • 2020-03-04
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      相关资源
      最近更新 更多