Заполнить конкретную базу данных данными factory_boy для тестирования

У меня есть приложение, в котором есть несколько неуправляемых моделей, которые извлекаются из таблицы в другой БД.

Я создал Фабрики для всех своих моделей, и в большинстве случаев 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.

Когда я запускаю свои тесты, он создает базу данных sqlite3 по умолчанию с именем defaultdb для запуска тестов (мы используем SQL Server в производстве, но из-за безопасности мы не можем предоставить django контроль над мастером для управления тестированием). Для этого мне пришлось создать обходной путь, но он работает.

Мои настройки выглядят так:

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 данными, подобными тем, которые есть у меня в моей модели фабричного мальчика? Я думаю, что это может решить проблему, с которой я столкнулся. Будет ли он? Я не уверена.

Б) Правильно ли так обращаться с менеджером на фабрике factory_boy? Я точно не знаю, как с этим справиться.


person Hanny    schedule 06.09.2018    source источник


Ответы (1)


В итоге я использовал Pytest-Django, так как эта среда тестирования фактически позволяет делать именно то, что я хотел.

Используя флаг --nomigrations, он берет мои модели, которые управляются только django в тестах, и создает для них соответствующее имя таблицы (используя их атрибут db_table) в тестовой базе данных. Затем я могу использовать factory_boy для создания фиктивных данных и их тестирования!

person Hanny    schedule 19.09.2018