아래의 링크에 이어서 쓰는 글이다.
들어가기 전 TMI를 하자면
이 글은 step1을 쓸때만 해도 코드를 발전시키면서 여러개의 글을 업데이트하려고 했지만
회사가 9월까지만 운영하고 문을 닫게 되면서 추가적인 코드는 업데이트하지 않게 되었다.
슬프게도 정말 삽질기록이 되어버렸지만
삽질을 통해서 그래도 많이 배울 수 있는 것 같다!
지난 글의 마지막 부분에서 썼듯
새로운 목표는 프로젝트 전체의 end point의 response를 테스트를 자동화 하는 것이다.
예를 들어
urlpatterns = [
path('crrent-user/', general.current_user_view),
path('languages/', general.language_view),
]
이런식의 url들이 있다면
1. 새로운 test file을 만들고
2. response를 받아오는 test class를 만드는 것까지만 우선 자동화하는 것이다.
class TestCurrentUserView(APITestCase):
print("CurrentUserView")
url = "/current-user/"
get_response = APIClient().get(url)
patch_response = APIClient().patch(url)
def test_status_code(self):
self.assertEqual(self.get_response.status_code, 401)
self.assertEqual(self.patch_response.status_code, 401)
여기까지는 성공을 했기 때문에(그리고 나서 들었던 회사 운영 중단 소식...또르르)
이 단계까지의 글을 써보려고 한다.
우선 커맨드로 특정 문자를 입력하면 파일이 생성되고 그 파일 안에 test class를 작성하는 거라서
command를 만드는 파일 안에 코드를 작성했다.
특정 앱 이름을 추가하면 그 앱에 해당하는 변수들을 셋팅해주도록 했다.
class Command(base.BaseCommand):
help = 'Do unit testing'
def add_arguments(self, parser):
parser.add_argument('app_name', type=str)
def handle(self, *args, **options):
if options['app_name'] == 'app1':
app_name = 'app1'
app_url = app1_url.urlpatterns
save_to = 'app1'
elif options['app_name'] == 'app2':
app_name = 'app2'
app_url = app2_url.urlpatterns
save_to = 'app2'
else:
print('Invalid app name')
app_name = ''
app_url = None
save_to = ''
아래의 코드는 파일을 원하는 위치에 만들고
내가 원하는 내용(classes)를 추가하는 기능을 한다.
만든 파일을 test로 실행하는 것까지를 목표로 했다.
# Make new file and write classes
f = open(current_path + f'/unit_test/{save_to}/test_class.py', 'w')
f.write(classes)
# run command
command = f'unit_test.{save_to}.test_class'
call_command("test", command)
이제 파일 안에 들어갈 테스트 클래스들을 만들어줘야 한다.
for loop로 url을 돌면서
url마다 테스트 클래스를 만들고자 했다.
파이썬 파일 가장 윗줄에 작성하는 import 부분을 먼저 넣어줬다.
from rest_framework.test import APITestCase, APIClient
class_name_list를 저장하는 이유는 하나의 url로 다양한 방법의 request를 보내는 경우(GET, POST, PATCH 등...)
test class 이름이 중복되어 생성되었기 때문에 이를 막고자
class_name_list에 class name을 저장해두고 같은 이름에는 뒤에 번호를 붙였기 때문이다.
classes = 'from rest_framework.test import APITestCase, APIClient\n' \
'\n'\
'\n'
class_name_list = []
어렵고 시간이 많이 걸렸던 부분은
url을 통해서 view 이름, method, permission 등을 찾아내는 작업이었다.
예를 들어 아래와 같은 urlpatterns에서 'current-url/', view의 이름(ex. current_user_view),
method(GET, PATCH, POST 등...), permission(AllowAny 등...)을 알아내려면 어떻게 해야 할까?
urlpatterns = [
path('crrent-user/', general.current_user_view),
path('languages/', general.language_view),
]
path(a, b)도 일종의 함수이기 때문에
path 속을 열심히 파고 print해가면서 찾을 수 있었다.
겨우 네줄이지만 정말이지 한참 걸렸던 것 같다.
for pattern in url_patterns:
url = f'/pub/{app_name}/{patterns.pattern}'
view = patterns.callback.__name__
methods = patterns.callback.cls.http_method_names
permission = patterns.callback.cls.permission_classes[0].__name__
클래스의 나머지 부분들은 정규표현식 등을 통해 채워나가서 어렵지 않게 구현할 수 있었다.
그래서 아래와 같은 형태의 permission에 따라 어떤 response가 있어야하는지 테스트 하는 부분까지 구현했다.
class TestCurrentUserView(APITestCase):
print("CurrentUserView")
url = "/current-user/"
get_response = APIClient().get(url)
patch_response = APIClient().patch(url)
def test_status_code(self):
self.assertEqual(self.get_response.status_code, 401)
self.assertEqual(self.patch_response.status_code, 401)
더 많은 기능을 추가하는 단계까지 가지는 못하게 되어서 아쉽지만
url을 통해서 method, permissoin, view 이름 등을 찾아보기 위해
path 함수를 공부하는 과정이 힘들어도 재미있었다!
'TIL' 카테고리의 다른 글
도커 볼륨 (0) | 2021.09.24 |
---|---|
도커 네트워크 (0) | 2021.09.14 |
도커 레지스트리 (0) | 2021.09.06 |
Week3 도커 이미지 (0) | 2021.09.03 |
[삽질 기록] Unit test 자동화하기 step1 (1) | 2021.08.27 |