Django manage.py测试无法正确加载夹具

时间:2021-10-06 00:56:51

I've written Django tests using django.test.TestCase, and I'd like to use a fixture with all of my current database data to run the tests. However, if I create the fixture as follows:

我使用django.test.TestCase编写了Django测试,我想使用一个包含所有当前数据库数据的fixture来运行测试。但是,如果我按如下方式创建夹具:

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

when I then run the tests using python manage.py test myapp, I get the following error:

当我然后使用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.

I read somewhere on SO that this might be caused by a pk conflict so I then tried re-creating the fixture with:

我在某处看到这可能是由于pk冲突造成的,所以我尝试用以下方法重新创建灯具:

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

But now running the test gives me:

但现在运行测试给了我:

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

I've also tried variously excluding (using the --exclude option) auth.permission and contenttypes (or both simultaneously), but then I get complaints about missing permissions (Key (permission_id)=(44) is not present in table "auth_permission".) or missing content types (DeserializationError: ContentType matching query does not exist.)

我也尝试过各种排除(使用--exclude选项)auth.permission和contenttypes(或同时两者),但后来我得到关于缺少权限的投诉(Key(permission_id)=(44)在表“auth_permission中不存在) “。)或缺少内容类型(DeserializationError:ContentType匹配查询不存在。)

The thing is, I need permissions anyway because my tests are partly to verify that only users with specific permissions can access certain views.

问题是,无论如何我需要权限,因为我的测试部分是为了验证只有具有特定权限的用户才能访问某些视图。

I don't understand why this is happening, to be honest--my impression was that the test runner starts with a completely clean database and loads EVERYTHING from my fixture, but reading posts like this one: Django unit-testing with loading fixtures for several dependent applications problems makes it seem like maybe that's not the case.

我不明白为什么会发生这种情况,说实话 - 我的印象是测试运行器从一个完全干净的数据库开始并从我的夹具中加载一切,但是阅读这样的帖子:Django单元测试与装载夹具几个依赖的应用程序问题似乎可能不是这样。

How can I get around this? I'd much rather not have to write stuff like User.objects.create_user(.. tons of times under def setUp(self): in my tests just to have enough objects for them to run properly...

我怎么能绕过这个?我宁愿不必编写像User.objects.create_user这样的东西(在def setUp(self)下很多次:在我的测试中只是为了让它们有足够的对象才能正常运行...

2 个解决方案

#1


3  

When you run a test the initial_data fixtures will be loaded (by syncdb).

运行测试时,将加载initial_data灯具(通过syncdb)。

For me dumpdata works with the --natural argument, excluding the contenttypes and then deleting some auth.permission entries manually that only these remain:

对我来说,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"
        ]
    }
},

I don't understand excactly why, but it works. I'd try to compare my fixture with a dump of a fresh database directly after syncdb and decide then what to delete or edit in my fixture. Hope this helps in your case.

我不明白为什么,但它的确有效。我试着在syncdb之后直接比较我的夹具和新数据库的转储,然后决定在我的夹具中删除或编辑什么。希望这对您的情况有所帮助。

#2


2  

The issue still seems to have been present, even with --natural. However, it seems to be resolved in django1.9 with new flags: dumpdata --natural-foreign --natural-primary

这个问题似乎仍然存在,即使是 - 自然。但是,它似乎在django1.9中用新标志解决:dumpdata --natural-foreign --natural-primary

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

#1


3  

When you run a test the initial_data fixtures will be loaded (by syncdb).

运行测试时,将加载initial_data灯具(通过syncdb)。

For me dumpdata works with the --natural argument, excluding the contenttypes and then deleting some auth.permission entries manually that only these remain:

对我来说,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"
        ]
    }
},

I don't understand excactly why, but it works. I'd try to compare my fixture with a dump of a fresh database directly after syncdb and decide then what to delete or edit in my fixture. Hope this helps in your case.

我不明白为什么,但它的确有效。我试着在syncdb之后直接比较我的夹具和新数据库的转储,然后决定在我的夹具中删除或编辑什么。希望这对您的情况有所帮助。

#2


2  

The issue still seems to have been present, even with --natural. However, it seems to be resolved in django1.9 with new flags: dumpdata --natural-foreign --natural-primary

这个问题似乎仍然存在,即使是 - 自然。但是,它似乎在django1.9中用新标志解决:dumpdata --natural-foreign --natural-primary

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