Unit test란 내가 작성한 코드의 가장 작은 단위인 함수를 테스트 하는 메소드이다. 그래서 내가 작성한 로직을 테스트하는 유닛테스트 코드를 작성하여 테스트 하게 된다.
Unit test를 왜 써야할까? 현재 나는 Django에서 여러가지 함수를 작성하고, Httpie 또는 Postman을 사용하여 내가 작성한 API가 제대로 동작하는지를 확인하였다. 하지만 이 과정에서 테스트 해야하는 API가 수십개라면 이걸 일일이 테스트하기란 효율적이지 못하다.
이처럼 unit test는 빠르고 비용이 싸기 때문에 개발 할 때 필수적으로 작성해야 한다.
unittest
라는 유닛테스트를 가능케 해주는 모듈이 이미 포함 되어 있습니다.unittest
외에도 pytest
라는 팩케지도 있습니다.pytest
를 선호 하지만 장고에서도 기본적으로 unittest
가 사용됨으로 unittest
를 사용해서 unit test를 구현하도록 하겠습니다.TestCase
: unittest 프레임 워크의 테스트 조직의 기본 단위Fixture
: 테스트를 진행할때 필요한 테스트용 데이터 혹은 설정 등을 이야기 한다. 주로 테스트 가 실행되기 전이나 후에 생긴다.assertion
: unittest에서 테스트 하는 부분이 제대로 됬는지를 확인하는 부분. Assertion이 실패하면 테스트도 실패한다.Python의 unittest
모듈을 사용하여 유닛 테스트를 개발할때 일반적으로 다음과 같은 절차를 따릅니다.
먼저 unittest 모듈을 import 한다.
import unittest
unittest.TestCase
클래스를 상속하는 테스트 클래스를 만든다.
class MyCalcTest(unittest.TestCase):
테스트 클래스 안에 test_
로 시작하는 테스트 메서드를 생성한다.
def test_add(self):
테스드 메서드에서는 일반적으로 테스트하고자 하는 함수나 메서드를 호출하고 그 결과값을 self.assert*()
메서드를 사용하여 확인한다. (assertEqual, assertTrue, assertFalse, assertRaises, assertRegex 등 다양한 assert 메서들을 사용할 수 있다).
def test_add(self):
c = myCalc.add(20, 10)
self.assertEqual(c, 30)
테스트 클래스가 완성되었으면, unittest.main()을 호출하여 테스트를 실행시킨다.
# mycalc.py
def add(a, b):
return a + b
def substract(a, b):
return a - b
# tests.py
import unittest
import mycalc
class MyCalcTest(unittest.TestCase):
def test_add(self):
c = mycalc.add(20, 10)
self.assertEqual(c, 30)
def test_substract(self):
c = mycalc.substract(20, 10)
self.assertEqual(c, 10)
if __name__ == '__main__':
unittest.main()
> python -m unittest --v
test_add (test_my_calc.MyCalcTest) ... ok
test_substract (test_my_calc.MyCalcTest) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
테스트 시나리오에 따라 어떤 경우는 테스트 전에 테스트를 위한 사전 준비 작업을 할 필요가 있습니다.또한 테스트가 끝난 후 테스트를 하기 위해 만든 리소스들을 정리(clean up)를 해야하는 경우도 있을 수 있습니다.unittest
는 이렇한 사전 준비 작업을 위해 setUp()
이라는 메서드를, clean up 처리를 위해 tearDown()
이라는 메서드를 제공합니다. 이러한 기능들을 Test Fixture라 하며, Fixture는 각각의 테스트 메서드가 실행되기 전과 후에 매번 실행됩니다.
import unittest
class MyCalcTest(unittest.TestCase):
def setUp(self):
print("1. Executing the setUp method")
self.fixture = { 'a' : 1 }
def tearDown(self):
print("3. Executing the tearDown method")
self.fixture = None
def test_fixture(self):
print("2. Executing the test_fixture method")
self.assertEqual(self.fixture['a'], 1)
> python -m unittest --v
test_fixture (test_my_calc.MyCalcTest) ...
1. Executing the setUp method
2. Executing the text_fixture method
3. Executing the tearDown method
ok
장고도 python의 unittest
라이브러리를 사용해서 테스트 하면 됩니다. 다음 링크를 참고하세요:
Unit test를 구현할때 지켜야 하는 일반적인 원칙들은 다음과 같습니다.
import json
from django.test import (
TestCase,
Client
)
from .models import User
# 설정한 엔드포인트 경로를 통해 함수를 호출. request나 http와 비슷한 일
client = Client()
# 테스트 케이스를 만들 때는 항상 TestCase() 객체를 상속받아 새로운 테스트 클래스를 생성한다.
class SignupTest(TestCase):
# 테스트 함수는 test_ 를 붙여주어야 테스트 함수로 인식한다.
def test_signup_post_success(self):
# 테스트를 위해 User Model의 Field값에 임의의 데이터를 저장한다.
data = {
'name' : '김해준',
'birthdate' : '1994-11-01',
'identifier' : 'hj1234',
'password' : '1q2w3e4r!',
'gender' : '남자',
'phone_number' : '01012345258',
'email' : 'qwer@qwer.com'
}
# post 함수에 대한 테스트이기 때문에 post로 작성을 한다.
# json.dumps 는 python 객체를 json string으로 변환하는 역할을 하는 함수
# content_type에서 형식을 json 형식으로 지정해줌
response = client.post('/user/signup', json.dumps(data), content_type = 'application/json')
# 반환되는 status_code와 message가 같은지 비교하여 같을 경우 테스트에서 OK를 띄워준다.
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), {
"message" : "SUCCESS"
})
현재 진행중인 본죽 클론 프로젝트에서 회원가입 시 메세지를 표시 해 줄 unit test를 작성해봤다.