# Django Unit tests
- Python 3.3 밑의 버전의 경우, unittest.mock 모듈의 백포트를 설치해야 함. - Django의 버전이 낮을 경우, settings file을 명시해 주어야 함. - Selenium 테스트 시, Selenium 2, Firefox, Python >= 2.6이 필요하며 selenium package(version > 2.13) 설치 필수. -> 실행 시에 --selenium 옵션으로 실행한다. $ ./runtests.py --settings=test_sqlite --selenium admin_inlines |
1. Django Unit test의 특징
- Django는 project나 app을 생성하게 되면 기본적으로 tests.py라는 파일이 생성된다.(unit test 코드를 이 파일에 작성)
- Python의 Unittest와 동일하게 작성. (자동으로 테스트 데이터베이스를 생성해주고 끝나면 삭제 해 줌.)
import unittest class TestClass1(unittest.TestCase): def test1(self): self.assertTrue(...) self.assertFalse(...) ... |
python manage.py test 로 실행가능 하며 각 앱만 unittest 구동하려하면 python manage.py test AppName 으로 실행할 수 있다.
- 함수 명은 반드시 test로 시작해야 함.
- 테스트 순서는 기본적으로 클래스(class)나 메서드(method)의 이름에 의존
class Test00Basic(unittest.TestCase): def test0000LibraryAAA(self): .... def test0001LibraryBBB(self): ... class Test01OtherLibrary(unittest.TestCase): def test0100ABC(self): ... |
순차적으로 실행되어야 할 테스트가 있다면 class와 method의 이름에 고유번호를 메기는 방식 적용.(오름차순)
2. 장고 테스트 실행 프레임워크(test-execution framework)
- django.test.TestCase
django.test.TestCase 는 각각 테스트의 트렌젝션의 분리를 제공합니다. 이 모듈은 클래스 기반 접근법으로 테스트를 정의합니다.
from django.test import TestCase class post(TestCase): print('test') |
- django.test.Client
django.test.Client 는 URL에 low-level HTTP 부터 페이지 컨텐츠까지 GET, POST 요청에 대한 응답을 시뮬레이팅 해줍니다.
from django.test import TestCase from django.test import Client class post(TestCase): c = Client() response = c.get('/board/get_post/32') print(response.status_code) response = c.post('/board/write_post/', {'author_id': '아이디', 'post_title': '제목', 'post_contents': '내용'}) print(response.status_code) |
# PyTest(py.test)
1. 장점
- DB 파일을 매번 새로 만들지 않는다. -> 테스트 실행 속도 향상
- 테스트 간 의존성을 관리할 수 있다.
- 테스트 동시 실행도 가능하다. (pytest-xdist 필요)
- 기존 테스트들과 호환된다.
2. 설치
pip install pytest-django |
pytest 뿐만 아니라 django의 테스트 코드를 인식하는 플러그인도 설치된다.
3. 병렬 실행
pip install pytest-xdist |
"pytest-xdist" 플러그인을 설치하여 테스트들을 병렬적으로 실행할 수 있다.
py.test -n 3 # 테스트가 3개씩 병렬적으로 실행됨 |
# test
test 함수 만들기 전 File : mysite.zip https://docs.djangoproject.com/en/1.7/intro/tutorial01/
1. 테스트 예제
import datetime from django.db import models from django.utils import timezone class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def __str__(self): return self.question_text def was_published_recently(self): return self.pub_date >= timezone.now() - datetime.timedelta(days=1) class Choice(models.Model): question = models.ForeignKey(Question) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) def __str__(self): return self.choice_text |
import datetime from django.utils import timezone from django.test import TestCase from polls.models import Question class QuestionMethodTests(TestCase): def test_was_published_recently_with_future_question(self): time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertEqual(future_question.was_published_recently(), False) |
polls.models.py 의 Question 모델 클래스에 있는 was_pulished_recently() 함수를 테스트하기 위한 파일이다.
2. 테스트 실행
- 명령어 실행
아래의 명령어를 통해 테스트를 실행할 수 있다.
python manage.py test polls |
C:\Users\hyuna\PycharmProjects\mysite>python manage.py test polls Creating test database for alias 'default'... F ====================================================================== FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionMethodTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\hyuna\PycharmProjects\mysite\polls\tests.py", line 13, in test_was_published_recently_with_future_question self.assertEqual(future_question.was_published_recently(), False) AssertionError: True != False ---------------------------------------------------------------------- Ran 1 test in 0.002s FAILED (failures=1) Destroying test database for alias 'default'... |
- 파이참 실행
파이참에서 테스트함수에서 마우스 우클릭을 하여 테스트를 실행할 수 있다.
테스트를 실행하면 다음과 가은 결과를 얻을 수 있다.
그리고 파이참에서는 다시 테스트를 쉽게 실행할 수 있도록 저장해준다.
- 실행 결과
- python manage.py test polls : polls 앱 안에 있는 테스트들을 모두 찾는다.
- django.test.TestCase 의 서브클래스를 발견한다.
- 테스팅 목적의 특수 데이터베이스를 만든다.
- test로 시작되는 이름을 가진 테스트 메서드를 찾는다
- test_was_published_recently_with_future_question 에서 pub_date 필드가 30일 미래로 되어 잇는 Question 인스턴스를 생성한다.
- assertEqual() 메서드를 사용하여 was_published_recently() 가 True를 리턴하고 비교값(False)와 다르다는 것을 확인했다.
- 버그 수정 후, 테스트 결과
# 에러가 발생하는 함수 수정 def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now |
버그 수정 후, 테스트를 통과하는 것을 확인할 수 있다.
3. 테스트 예제(2)와 실행
import datetime from django.utils import timezone from django.test import TestCase from polls.models import Question class QuestionMethodTests(TestCase): def test_was_published_recently_with_future_question(self): time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertEqual(future_question.was_published_recently(), False) def test_was_published_recently_with_old_question(self): time = timezone.now() - datetime.timedelta(days=30) old_question = Question(pub_date=time) self.assertEqual(old_question.was_published_recently(), False) def test_was_published_recently_with_recent_question(self): time = timezone.now() - datetime.timedelta(hours=1) recent_question = Question(pub_date=time) self.assertEqual(recent_question.was_published_recently(), True) |
좀 더 확실한 테스트를 위해, 테스트 함수를 추가했다.
"Run/Debug Configurations"에서 테스트를 한 번에 수행할 수 있도록 추가한다.
테스트 결과, 3개의 테스트 모두 성공한 것을 확인할 수 있다.
'Python > Django' 카테고리의 다른 글
[Django] File upload (FileField, ImageField) (0) | 2016.10.19 |
---|---|
[Django] uwsgi + nginx in ubuntu (0) | 2016.10.18 |
[Django] Extra (0) | 2016.10.06 |
[Django] Filter vs Exclude (0) | 2016.10.04 |
[Django] Custom Model Fields (0) | 2016.09.29 |
댓글