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

时间:2013-08-22 08:29:20

标签: django unit-testing django-testing django-fixtures

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

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.

我在某处读到这可能是由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.permissioncontenttypes(或同时使用两者),但后来我抱怨缺少权限({{1} })或缺少内容类型(Key (permission_id)=(44) is not present in table "auth_permission".

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

我不明白为什么会发生这种情况,说实话 - 我的印象是测试运行器从一个完全干净的数据库开始并从我的装置中加载一切,但是阅读这样的帖子:Django unit-testing with loading fixtures for several dependent applications problems看起来似乎并非如此。

我该如何解决这个问题?我宁愿不要写像这样的东西 在我的测试中,DeserializationError: ContentType matching query does not exist.User.objects.create_user(..吨次,只是为了让他们有足够的物品才能正常运行......

2 个答案:

答案 0 :(得分:3)

当您运行initial_data fixtures will be loaded (by 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之后直接比较我的夹具和新数据库的转储,然后决定在我的夹具中删除或编辑什么。希望这对您的情况有所帮助。

答案 1 :(得分:3)

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

请参阅https://code.djangoproject.com/ticket/21278#comment:5