2017-02-14 13 views
3

私はpytest 3.0.6とpytest-django 3.1.2を使用してDjangoのライブラリで作業しています。私はこの非常に簡単なテスト失敗を持っている、と私は起こるのか理解していない:Pytest-django:ユーザ権限を設定する

# test_mytest.py 
import pytest 
from django.contrib.auth.models import Permission 
from django.contrib.contenttypes.models import ContentType 


@pytest.mark.django_db 
def test_user_has_perm(django_user_model): 
    # Create a new user 
    john_doe = django_user_model.objects.create_user('johndoe', email='[email protected]', password='123456') 

    # Get or create the permission to set on user 
    user_ct = ContentType.objects.get(app_label='auth', model='user') 
    p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user") 

    # User don't have the permission 
    assert john_doe.has_perm(p) is False 

    # Set permission to user 
    john_doe.user_permissions.add(p) 
    assert john_doe.has_perm(p) is True # ---> FAIL 

念のために、テストの結果は次のとおりです。

$ pytest 
============================= test session starts ============================= 
platform win32 -- Python 3.5.3, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 
Django settings: testsite.settings (from ini file) 
rootdir: D:\Dev\foss\django-modern-rpc, inifile: tox.ini 
plugins: pythonpath-0.7.1, django-3.1.2, cov-2.4.0 
collected 1 items 

modernrpc\tests\test_test_test.py F 

================================== FAILURES =================================== 
_____________________________ test_user_has_perm ______________________________ 

django_user_model = <class 'django.contrib.auth.models.User'> 

    @pytest.mark.django_db 
    def test_user_has_perm(django_user_model): 
     # Create a new user 
     john_doe = django_user_model.objects.create_user('johndoe', email='[email protected]', password='123456') 

     # Get or create the permission to set on user 
     user_ct = ContentType.objects.get(app_label='auth', model='user') 
     p, _ = Permission.objects.get_or_create(content_type=user_ct, codename='delete_user', name="Can delete user") 

     # User don't have the permission 
     assert john_doe.has_perm(p) is False 

     # Set permission to user 
     john_doe.user_permissions.add(p) 
>  assert john_doe.has_perm(p) is True # ---> FAIL 
E  assert False is True 
E  + where False = <bound method PermissionsMixin.has_perm of <User: johndoe>>(<Permission: auth | user | Can delete user>) 
E  + where <bound method PermissionsMixin.has_perm of <User: johndoe>> = <User: johndoe>.has_perm 

modernrpc\tests\test_test_test.py:20: AssertionError 
========================== 1 failed in 0.32 seconds =========================== 

tox.iniからconfigブロック、

BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 
DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.sqlite3', 
     'NAME': os.path.join(BASE_DIR, 'modern_rpc.sqlite3'), 
    }, 
} 
:テスト設定から

[pytest] 
DJANGO_SETTINGS_MODULE = testsite.settings 
norecursedirs = .git __pycache__ build dist venv* .tox .vscode .cache *.egg-info 
python_paths = modernrpc/tests 
testpaths = modernrpc/tests 
python_files = test_*.py dummy_*.py 

とDBの構成、

私は何が間違っていますか? docsから

答えて

4

を再フェッチした後、あなたは文字列'app_label.codename'を使用する必要が動作します。

trueを返し、ユーザは「パーマが形式である指定されたアクセス権を持っている場合<アプリラベル>。<許可コード名> "です。

あなたはhas_permへの最後の呼び出しのための権限を変更または全くキャッシュが存在しないことを確認するためにDBからこのユーザーの新しいインスタンスを取得している場合にも、あなたはuser._perm_cacheuser._user_perm_cacheをクリアする必要があります。

del john_doe._perm_cache 
del john_doe._user_perm_cache 
# OR 
john_doe = django_user_model.objects.get(username='johndoe') 

これは、has_permがauthバックエンドを呼び出し、次にこれらのキャッシュを最初に参照するためです。

+0

ありがとう、私は完全にアクセス許可のキャッシュシステムを逃した。 – Antwane

+0

うん。 Djangoは、キャッシングがうまく文書化されていないので、コードを掘り下げます。 – schwobaseggl

2

has_perm(パーマ、OBJ =なし)ユーザーはパーマがフォーマット

"<app label>.<permission codename>"にある指定されたアクセス権を持っている場合

trueを返します。

(アクセス許可に関するドキュメントを参照)。ユーザーが非アクティブの場合、このメソッド は常にFalseを返します。

objが渡された場合、このメソッドはモデルのパーミッションをチェックするのではなく、この特定のオブジェクトのパーミッションをチェックします。

だから、このメソッドは文字列ではないアクセス許可オブジェクト

john_doe.has_perm('auth.delete_user')

Trueを返す必要があります受け付けます。 (user_ctのアプリがauthの場合は、の許可は、user_ctを使用して作成したため、authアプリが割り当てられています。

permission check cachingがあるため、この例ではすぐには発生しません。

それはあなたがオブジェクト

#Be aware this only works after Django 1.9+ 
#https://code.djangoproject.com/ticket/26514 
john_doe.refresh_from_db() 
#Otherwise use: 
john_doe = User.objects.get(pk=john_doe.pk)