Testing Pyramid
- 피라미드를 나누고 있는 각각의 요소가 특정 테스트 방법
- E2E <- Integration <- Unit 순으로 테스트의 난이도가 올라간다.
- 가장 아래의 Unit Test를 전체의 70%, Integration Test를 전체의 20%, E2E Test를 전체의 10%로 전체 테스트를 구성하는 것을 제안
Testing Methods
- E2E(End to End) Testing / UI Testing
- 웹 브라우저를 통해서 직점 웹 사이트에 접속해서 여러가지 기능들을 테스트하는 방법.
- Manual(수동) Testing을 통해서 진행하든 자동화를 통해서 진행하든 굉장히 까다롭고 어렵다.
- Integration Testin
- 두개 이상의 클래스 또는 서브 시스템의 결합을 테스트하는 방법으로 예를 들면 장고 서버를 실행해서 데이터베이스 시스템과 연동을 테스트하는 것
- Httpie나 Postman을 사용해서 테스트를 진행하는 편
- Unit Testing
- 가장 쉽고 효과가 좋은 테스트 방법
- 시스템의 가장 작은 단위인 함수에 대한 테스트를 진행한다.
- 장점
- UI Testing, Integration Testing에 비해서 테스트에 소모되는 여러 비용이 저렴하다.
- 스크립트를 통해서 각각의 테스트를 자동으로 수행할 수 있다.
- 다른 테스트에 비해서 진행 속도도 매우 빠르다.
- Unit Test 집합을 잘 구성해 놓으면 이후의 유지-보수에도 도움이 된다.
- Regression Test를 쉽게 반복 수행할 수 있다.
- Regression Test란 이전에 통과했던 Unit Test 집합을 사용해서 현재의 버그를 찾아내는 테스트 방법으로 이전에 통과했던 Unit Test가 잘 구성된 집합이었다면 추후에도 도움이 될 가능성이 크다.
Test의 일반 원칙
- 각각의 테스트 유닛은 가장 작은 단위이 집중해야하며, 해당 기능이 정확하게 동작하는 지를 증명해야 한다.
- 각각의 테스트 유닛은 독립적이어야 한다. 단독으로도 실행가능해야 하고, 테스트 슈트를 통해서도 실행되어야 한다.
- 호출순서와 무관하게 작동해야 한다.
- 기존의 데이터와는 무관한 완전히 새로운 데이터 세트로 테스트를 진행해야 하며, 결과는 반드시 지워야 한다.
- 테스트가 빠르게 수행되도록 노력해야한다.
- 불가피하게 무거운 데이터를 다뤄야 하는 테스트의 경우는 별도의 테스트 슈트(일련의 연속된 테스트)로 분리하여 관리한다.
- 현재 사용중인 툴에 대해서 개별 테스트나 테스트 케이스에 대해서 어떻게 수행하는지에 대해서 알아두어야 한다.
- 하루 작업의 시작과 끝에 풀 테스트 슈트(구성한 전체 테스트)를 진행하는 습관을 들이면 좋다.
- 작업 전 문제가 없는 상태임을 확인하고, 작업 후에도 문제가 없을 확인하는 것
- 공유 저장소로 소스를 Push하기 전에 자동적으로 풀 테스트를 진행하는 것이 좋다.
- 해당되는 훅을 구현해 놓는게 좋다.
- 일종의 책갈피로서 다음 작업까지 텀이 길어질 것 같다면 필요한 지점에 일부러 실패를 유발하는 테스트를 만들어 놓는 것도 좋은 활용법
- 테스트 이름은 길고 서술적이어야 한다.
- 테스트 이름은 직접 노출될 일이 없고, 실패할 때에만 노출이 되는데 이 때 표시되는 이름을 통해서 어떤 부분에 문제가 있는지 파악을 하기 때문
- 잘 구성된 테스트 코드는 그 자체로서 개발 문서로 활용할 수 있다.
- 테스트 코드의 구성을 통해서 전체적인 구성을 파악할 수 있다.
- 어떤 부분이 까다로운지, 어떤 부분이 수정이 필요할지 등등에 대한 대략적인 정보를 습득할 수 있다.
Django 프로젝트에 Unit Test를 적용해보기
- 현재 진행중인 t2tea.com 페이지 클로닝 프로젝트에서 사용중인 회원가입 및 로그인 기능에 Unit Test를 적용해보기로 했다.
######################################################
# /__PROJECT_ROOT__/user/tests.py
import json
import unittest
from django.test import Client, TestCase
client = Client()
class UnitTest(TestCase):
test_user_data = {
'first_name' : 'TEST1',
'last_name' : 'Mr1',
'phone' : '010-1111-0101',
'email' : 'MrTEST1@email.com',
'password' : '1q2w3e4r5t6ASD',
'birthdate' : '2020-08-20',
'is_newsletter_subscribed' : False
}
def test_JoinView(self):
response = client.post('/user/join', json.dumps(self.test_user_data), content_type = 'application/json')
self.assertEqual(response.status_code, 200)
def test_LoginView(self):
client.post('/user/join', json.dumps(self.test_user_data), content_type = 'application/json')
test_login_data = {
'email' : 'MrTEST1@email.com',
'password' : '1q2w3e4r5t6ASD'
}
response = client.post('/user/login', json.dumps(test_login_data), content_type = 'application/json')
self.assertEqual(response.status_code, 200)
#############################################################
# 실행 결과
>>> python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.664s
OK
Destroying test database for alias 'default'...
- tests.py 코드 분석
- 일단 일련의 테스트 과정에서 사용할 데이터 세트를 미리 선언한 후에 테스트에 사용했다.
- user App에 구현한 회원가입('/user/join') 및 로그인('/user/login') 엔드포인트에 대한 테스트를 진행했다.
- 로그인 기능의 경우에는 회원가입이 선행되어야 진행이 가능하기 때문에 회원가입을 위한 POST를 1차적으로 진행해 주었다.
- 전체 테스트 진행 결과는 OK지만, 테스트 케이스가 단순했기 때문에 더 보완할 필요가 있어보인다.
- manage.py test
- 풀 테스트 슈트를 진행하는 명령어로 전체 유닛 테스트를 진행한다.
- 명령어 구성 ex) python manage.py test [user.tests.UnitTest.test_JoinView]
- 대괄호로 감싼 부분에 대해서 공백일 경우에는 풀 테스트를 진행한다.
- 대괄호 부분에 적을 수 있는 내용은 <APP_NAME> . <tests.py> . <TEST_CLASS> . <TEST_FUNCTION_NAME> 순으로 구성
Unit Test 에 대한 느낀점
- 전에는 기능 테스트를 위해서 장고 서버를 실행 한 후에 Httpie를 사용하는 방법을 썼었는데, 그러다보니 의미없는 테스트 데이터가 계속해서 DB에 쌓이는 문제가 발생했었다.
- Unit Test라는 방법이 더 간단하기도 하고, 적절한 테스트 방법이라는 것을 알게 되었으니 앞으로 자주 사용하는 습관을 가지도록 노력하자.
'wecode > TIL 정리' 카테고리의 다른 글
Django TIL - 2. Select Related, Prefetch Related (0) | 2020.09.17 |
---|---|
자료구조 TIL - 4. Tree (0) | 2020.09.03 |
자료구조 TIL - 3. Stack, Queue (0) | 2020.08.22 |
자료구조 TIL - 2. Set, Dictionary, Hash (0) | 2020.08.12 |
위코드 Foundation - Bcrypt, JWT 테스트 (0) | 2020.08.12 |