Django, Django Rest-Framework 및 Djoser를 테스트하는 방법
요구 사항
이메일 활성화와 함께 django, django restframework 및 djoser를 사용하고 있지만 인증을 테스트하는 데 어려움을 겪고 있습니까? 그 문제를 잠시 후에 해결해 봅시다.
먼저 설정 파일을 프로덕션, 개발 및 테스트로 분리해야 합니다. 구조는 이렇게 생겼어요
settings/
__init__.py
base.py
production.py
development.py
testing.py
가장 먼저 해야 할 일은 기본 프로젝트 내에
settings
라는 폴더를 만드는 것입니다. 폴더 이름에 주의하세요. settings.py
와 정확히 동일해야 하지만 .py
는 없어야 합니다.다음으로 아래 파일을 만듭니다.
__init__.py
base.py
production.py
development.py
testing.py
이러한 파일은 개발 시 제안된 이름으로 사용됩니다. django 설정은
development.py
를 사용하고 테스트하는 동안에는 testing.py
를 사용합니다.이제 모든 프로젝트에 대한 공통 설정을
base.py
에 복사해 보겠습니다. 모든 프로젝트에 공통적인 사항을 식별하는 것은 귀하에게 달려 있습니다.내 경우에는
base.py
에 대해 다음을 입력합니다.BASE_DIR
SECRET_KEY # read from environment variable
INSTALLED_APPS
MIDDLEWARE
ROOT_URLCONF
TEMPLATES
WSGI_APPLICATION
AUTH_PASSWORD_VALIDATORS
LANGUAGE_CODE
TIME_ZONE
USE_I18N
USE_TZ
STATIC_URL
DEFAULT_AUTO_FIELD
AUTH_USER_MODEL
# emial related parameter are read from env in my case
EMAIL_BACKEND
EMAIL_HOST
EMAIL_PORT
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
EMAIL_USE_TLS
REST_FRAMEWORK # depends on your choice of drf settings
DJOSER # common setting only we will extend it in other files
production.py
에 대한from .base import *
DEBUG = False
ALLOWED_HOSTS = ['yoursite.com'] # up to you choice what to allow
DATABASES # i use different db for prod
DJOSER.update({
....
}) # i use different conf for prod
development.py
에 대한from .base import *
DEBUG = True
ALLOWED_HOSTS = ['*'] # up to you choice what to allow
DATABASES # i use different db for dev
DJOSER.update({
....
}) # i use different conf for dev
for
testing.py
는 이 파일을 자세히 볼 수 있지만 지금은from .base import *
DEBUG = True
ALLOWED_HOSTS = ['*'] # up to you choice what to allow
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DATABASES # i use different db for test
DJOSER.update({
....
}) # i use different conf for test
이제 마지막 파일은
__init__.py
이 파일은 설정을 동적으로 로드합니다.import os
from . import base
enviroment = os.environ.get('ENVIROMENT', 'development')
if enviroment == 'production':
from .production import *
elif enviroment == 'testing':
from .testing import *
else:
from .development import *
Djoser는 다른 용도로 다른 직렬 변환기 클래스를 사용하지만 문서를 확인하는 데만 집중합니다Email serialzers.
이제
testing.py
파일을 작성해 보겠습니다.from .base import *
DEBUG = True
ALLOWED_HOSTS = ['*']
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# for postgresql: i use postgres
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'djoser',
'USER': 'djoser',
'PASSWORD': 'djoser',
'HOST': 'localhost',
'PORT': '5432',
}
# for mysql:
# 'default': {
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'djoser',
# 'USER': 'djoser',
# 'PASSWORD': 'djoser',
# 'HOST': 'localhost',
# 'PORT': '3306',
# }
}
DJOSER_EMAIL = {
'activation': 'your-authentication-app.email.ActivationEmail'
}
if 'EMAIL' in DJOSER:
DJOSER['EMAIL'].update(DJOSER_EMAIL)
else:
DJOSER['EMAIL'] = DJOSER_EMAIL
에서 알아차리면
DJOSER_EMAIL = {
'activation': 'your-authentication-app.email.ActivationEmail'
}
이메일 활성화 시리얼라이저를
your-authentication-app.email.ActivationEmail
로 재정의하지만 아직 존재하지 않으므로 지금 생성해 보겠습니다.인증 앱에서
email.py
라는 파일을 만들고 아래의 직렬 변환기를 넣고 이야기해 봅시다.from django.contrib.auth.tokens import default_token_generator
# djoser imports
from templated_mail.mail import BaseEmailMessage
from djoser import utils
from djoser.conf import settings
EMAILS = {}
class ActivationEmail(BaseEmailMessage):
"""Email Activation Token Generator
"""
template_name = "email/activation.html"
def get_context_data(self):
# ActivationEmail can be deleted
context = super().get_context_data()
user = context.get("user")
context["uid"] = utils.encode_uid(user.pk)
context["token"] = default_token_generator.make_token(user)
context["url"] = settings.ACTIVATION_URL.format(**context)
uid, token = context['uid'], context['token']
# here we store all the requested tokens in a dictionary for later use
EMAILS[user.email] = {'uid': uid, 'token': token}
return context
djoser 직렬 변환기에서 추가하는 유일한 것은
EMAIL = {}
...
EMAILS[user.email] = {'uid': uid, 'token': token}
서버에서 보낸 이메일을 저장하는 데 사용됩니다.
참고: 테스트하는 동안 django가 실제 이메일을 보내는 것을 원하지 않기 때문에
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
를 사용하고 있습니다.이제 우리는 사용자를 테스트할 것입니다. 테스트할 몇 가지 사례가 있지만 그 동안 무엇을 테스트할지는 스스로 결정해야 합니다.
from django.urls import reverse
from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.test import APITestCase
User = get_user_model()
class UserViewSetTest(APITestCase):
def setUp(self):
"""
Set up method which is used to initialize before any test run.
"""
self.user_info = self.generate_user_info()
def generate_user_info(self):
"""Generate user data for new user.
Returns:
Dict: dictionary of the test user data.
"""
return {
"first_name": "fake.first_name()",
"last_name": "fake.last_name()",
"username": "fake.user_name()",
"password": "fake.password()",
}
def test_create_user(self):
"""
Test for creating users using API.
"""
url = reverse("user-list")
response = self.client.post(
url,
self.user_info,
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
user = User.objects.get(id=response.data['id'])
self.assertEqual(user.email, self.user_info["email"])
self.assertEqual(user.username, self.user_info["username"])
# self.assertEqual(user.ssn, self.user_info["ssn"])
self.assertTrue(user.password is not self.user_info["password"])
self.assertTrue(user.is_deleted is not True)
self.assertTrue(user.father_first_name is None)
self.assertTrue(user.mother_first_name is None)
self.assertTrue(user.password is not None)
self.assertTrue(user.birth_date is not None)
def test_get_token(self):
"""
This test is used to test the login API. getting token and testing the token.
"""
# Create a new user to login
user_info = self.generate_user_info()
new_user = self.client.post(
reverse("user-list"),
user_info,
)
self.assertEqual(new_user.status_code, status.HTTP_201_CREATED)
# Activation of User
from authentications.email import EMAILS
activation_url = reverse('user-activation')
activation_data = EMAILS[user_info["email"]]
self.client.post(activation_url, activation_data)
url = reverse("jwt-create")
data = {
"username": user_info["username"],
"password": user_info["password"],
}
response = self.client.post(url, data)
self.assertTrue(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data["access"] is not None)
def test_get_user(self):
"""
This test for retrieving single user using API.
"""
# Create a new user to login
new_user = self.client.post(
reverse("user-list"),
self.user_info,
)
self.assertEqual(new_user.status_code, status.HTTP_201_CREATED)
# Activate User
from authentications.email import EMAILS
activation_url = "http://127.0.0.1:8000/auth/users/activation/"
activation_data = EMAILS[self.user_info["email"]]
self.client.post(activation_url, activation_data)
# Get token
url = reverse("jwt-create")
data = {
"username": self.user_info["username"],
"password": self.user_info["password"],
}
response = self.client.post(url, data)
self.assertTrue(response.status_code, status.HTTP_200_OK)
# Get user
token = response.data["access"]
self.client.credentials(HTTP_AUTHORIZATION=f"JWT {token}")
url = reverse('user-list', kwargs={'id':new_user.data["id"]})
get_user = self.client.get(url)
self.assertEqual(get_user.status_code, status.HTTP_200_OK)
self.assertEqual(get_user.data["id"], new_user.data["id"])
self.assertEqual(get_user.data["email"], new_user.data["email"])
test_user = self.client.post(
reverse("user-list"),
self.generate_user_info(),
)
url = url = reverse('user-list', kwargs={'id': test_user.data['id'] })
get_user = self.client.get(url)
self.assertEqual(get_user.status_code, status.HTTP_404_NOT_FOUND)
위의 테스트에는 원하는 테스트 유형이 있지만 이 블로그의 주요 목적은 전자 메일 활성화를 사용하여 djoser를 테스트하는 방법을 알려주는 것입니다.
그것이 당신을 돕기를 바랍니다.
즐기다.
Reference
이 문제에 관하여(Django, Django Rest-Framework 및 Djoser를 테스트하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/chapimenge3/how-to-test-django-django-rest-framework-and-djoser-750텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)