Тест Django manage.py не может правильно загрузить приспособление

Я написал тесты Django, используя django.test.TestCase, и я хотел бы использовать приспособление со всеми данными моей текущей базы данных для запуска тестов. Однако, если я создам приспособление следующим образом:

python manage.py dumpdata --indent=3 > myapp/fixtures/test_data.json

когда я затем запускаю тесты, используя python manage.py test myapp, я получаю следующую ошибку:

Problem installing fixture...(traceback)
IntegrityError: Could not load auth.Permission(pk=42): duplicate key value violates unique constraint "auth_permission_content_type_id_codename_key"
DETAIL:  Key (content_type_id, codename)=(14, add_record) already exists.

Я где-то читал на SO, что это может быть вызвано конфликтом pk, поэтому я попытался воссоздать прибор с помощью:

python manage.py dumpdata --natural --indent=3 > myapp/fixtures/test_data.json

Но теперь запуск теста дает мне:

Problem installing fixture...(traceback)
DeserializationError: 'NoneType' object has no attribute '_meta'

Я также пробовал по-разному исключать (используя параметр --exclude) auth.permission и contenttypes (или оба одновременно), но потом я получаю жалобы на отсутствие разрешений (Key (permission_id)=(44) is not present in table "auth_permission".) или типов содержимого (DeserializationError: ContentType matching query does not exist.)

Дело в том, что мне все равно нужны разрешения, потому что мои тесты частично предназначены для проверки того, что только пользователи с определенными разрешениями могут получить доступ к определенным представлениям.

Честно говоря, я не понимаю, почему это происходит - у меня сложилось впечатление, что средство запуска тестов запускается с полностью чистой базой данных и загружает ВСЕ из моего устройства, но читает такие сообщения: Модульное тестирование Django с загрузкой фикстур для нескольких проблем зависимых приложений кажется, что это не так.

Как я могу это обойти? Я бы предпочел не писать такие вещи, как User.objects.create_user(.. тонны раз под def setUp(self): в моих тестах, просто чтобы было достаточно объектов для их правильной работы ...


person GChorn    schedule 22.08.2013    source источник


Ответы (2)


Кажется, проблема все еще существует, даже с --естественным. Однако, похоже, это решено в django1.9 с новыми флагами: dumpdata --natural-foreign --natural-primary

см. https://code.djangoproject.com/ticket/21278#comment:5

person powderflask    schedule 10.08.2016
comment
Для тех, кто обнаружит это с подобной проблемой, вот КЛЮЧЕВАЯ идея: если ваши модели содержат отношение M2M, НЕ выгружайте таблицу M2M в свой тестовый прибор! В противном случае M2M будет сначала заполнен при создании связанных объектов, а затем СНОВА, когда данные M2M загружаются из прибора, что вызовет ошибку целостности. - person powderflask; 11.08.2016

Когда вы запускаете тест, фикстуры initial_data будут загружено (пользователем syncdb).

Для меня dumpdata работает с аргументом --natural, исключая contenttypes, а затем вручную удаляя некоторые auth.permission записи, которые остались только:

{
    "pk": 1, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_permission", 
        "name": "Can add permission", 
        "content_type": [
            "auth", 
            "permission"
        ]
    }
},
{
    "pk": 2, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_permission", 
        "name": "Can change permission", 
        "content_type": [
            "auth", 
            "permission"
        ]
    }
},
{
    "pk": 3, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_permission", 
        "name": "Can delete permission", 
        "content_type": [
            "auth", 
            "permission"
        ]
    }
},
{
    "pk": 4, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_group", 
        "name": "Can add group", 
        "content_type": [
            "auth", 
            "group"
        ]
    }
},
{
    "pk": 5, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_group", 
        "name": "Can change group", 
        "content_type": [
            "auth", 
            "group"
        ]
    }
},
{
    "pk": 6, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_group", 
        "name": "Can delete group", 
        "content_type": [
            "auth", 
            "group"
        ]
    }
},
{
    "pk": 7, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_user", 
        "name": "Can add user", 
        "content_type": [
            "auth", 
            "user"
        ]
    }
},
{
    "pk": 8, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_user", 
        "name": "Can change user", 
        "content_type": [
            "auth", 
            "user"
        ]
    }
},
{
    "pk": 9, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_user", 
        "name": "Can delete user", 
        "content_type": [
            "auth", 
            "user"
        ]
    }
},
{
    "pk": 10, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_contenttype", 
        "name": "Can add content type", 
        "content_type": [
            "contenttypes", 
            "contenttype"
        ]
    }
},
{
    "pk": 11, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_contenttype", 
        "name": "Can change content type", 
        "content_type": [
            "contenttypes", 
            "contenttype"
        ]
    }
},
{
    "pk": 12, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_contenttype", 
        "name": "Can delete content type", 
        "content_type": [
            "contenttypes", 
            "contenttype"
        ]
    }
},
{
    "pk": 13, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_session", 
        "name": "Can add session", 
        "content_type": [
            "sessions", 
            "session"
        ]
    }
},
{
    "pk": 14, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_session", 
        "name": "Can change session", 
        "content_type": [
            "sessions", 
            "session"
        ]
    }
},
{
    "pk": 15, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_session", 
        "name": "Can delete session", 
        "content_type": [
            "sessions", 
            "session"
        ]
    }
},
{
    "pk": 16, 
    "model": "auth.permission", 
    "fields": {
        "codename": "add_site", 
        "name": "Can add site", 
        "content_type": [
            "sites", 
            "site"
        ]
    }
},
{
    "pk": 17, 
    "model": "auth.permission", 
    "fields": {
        "codename": "change_site", 
        "name": "Can change site", 
        "content_type": [
            "sites", 
            "site"
        ]
    }
},
{
    "pk": 18, 
    "model": "auth.permission", 
    "fields": {
        "codename": "delete_site", 
        "name": "Can delete site", 
        "content_type": [
            "sites", 
            "site"
        ]
    }
},

Я не понимаю, почему, но это работает. Я бы попытался сравнить свое устройство с дампом новой базы данных сразу после syncdb и решить, что удалить или отредактировать в моем устройстве. Надеюсь, это поможет в вашем случае.

person yofee    schedule 10.11.2013