
pytest-django는 django 프로젝트에서 pytest를 사용하기 위한 플러그인pytest와 pytest-django는 Standard Django Test suite와 Nose Test suite 호환됨django의 manage.py test를 사용하지 않고 pytest 명령어를 사용manage.py를 사용하지 않는 이유는 unittest를 임포트해서 TestCase 클래스의 서브 클래스로 선언할 필요가 없고, 단순하게 테스트 함수만 작성하는 것만으로 테스트를 작성할 수 있기 때문Fixture를 관리할 수 있는 편리함과 pytest의 다양한 플러그인도 사용할 수 있다는 장점이 있음django에는 기본 테스트 모듈이 내재 되어 있음Pytest를 별도로 실행을 해야하는 걸까?django 내장 테스트는 Boiler-Plate가 존재set이 단일 클래스(django.test.TestCase)를 상속받아 운영pytest는 멀티 실행을 지원Tip!
Boiler-Plate(보일러플레이트)란?
- 최소한의 변경으로 여러 곳에서 재사용되며 반복적으로 비슷한 형태를 띄는 코드를 말함
- 어원: 보일러플레이트 코드의 어원은 신문사업에서 나왔음
- 1890년대에 광고나 컬럼과 같이 계속 사용되는 텍스트 인쇄판은 부드러운 납 대신 강철로 찍기 시작했는데 이를
Boiler-Plate라고 불렀음
djangoclass 상속으로 이루어짐assert를 각 class의 method로 평가해야 함pytestfunction 단위로 테스트를 작성 할 수 있음assert로 테스트를 평가할 수 있음django 외 다른 파이썬 프로젝트에도 도입이 가능config를 파일로 지정해 놓을 수 있으며 fixture를 정해놓고 여러 곳에서 원하는 순서에 맞추어 실행시켜 볼 수 있음$ pip install pytest-django
# pytest.ini - Project root folder
# 아래 설정을 잡아 주지 않을 경우, pytest 실행 시 에러 발생
[pytest]
DJANGO_SETTINGS_MODULE = project.settings
django 프로젝트의 설정을 사용하기 때문에 pytest.ini 파일에 위와 같이 명시하거나 --ds=project.settings 또는 DJANGO_SETTINGS_MODULE 환경변수를 설정해야 함python path 관리pytest-django는 기본적으로 프로젝트의 manage.py 파일을 찾아보고 그 디렉토리를 python path에 자동으로 추가함$ pytest test.py directory
pytest-django는 manage.py 또는 django-admin.py를 이용해 테스트를 실행하지 않고, 단독으로 pytest 명령어를 실행하는 방식을 사용pytest.ini에서 지정 가능[pytest]
addopts = --reuse-db
—db-reuse
—create-db
models 변경 사항을 반영 할 수 있음default로 —db-reuse를 기본으로 설정해두고 DB 스키마 변경시에만 사용하는 것을 추천—migrationmodels 스키마 변경이 있을 경우 migration을 진행django DB 가 아닌 테스트용 DB에 적용—no-migrationpytest-django는 테스트할 때 DB를 접근하는 것에 대해 보수적으로 다룸pytset-django는 pytest mark를 사용pytest.marks.db_djangomarks를 활용import pytest
@pytest.mark.django_db
def test_my_user():
me = User.objects.get(username='me')
assert me.is_superuser
mark를 설정할 경우 모든 테스트에 적용할 수 있음import pytest
pytestmark = pytest.mark.django_db
@pytest.mark.django_db
class TestUsers:
pytestmark = pytest.mark.django_db
def test_my_user(self):
me = User.objects.get(username='me')
assert me.is_superuser
django 자체에 TransactionTestCase 클래스는 트랜젝션을 통해 격리된 상태에서 테스트를 수행하게 하고, 테스트를 마치면 DB 초기화를 해줌django_db mark에 Transaction=True 파라미터를 전달@pytest.mark.django_db(transaction=True)
def test_spam():
pass
--reuse-db은 데이터베이스를 재사용하기 위한 실행 옵션이고, --create-db는 데이터베이스를 강제로 다시 생성하는 실행 옵션--reuse-db를 사용하면 새로운 테스트 전용 DB가 생성되는데 모든 테스트가 종료 되더라도 테스트 DB는 지워지지 않음--reuse-db를 사용하면 이전 테스트 DB를 다시 사용하게 됨--reuse-db 옵션을 기본 pytest.ini 옵션으로 지정하고, 스키마가 변경되었거나 했을 때 --create-db 옵션을 사용하는 것을 추천[pytest]
addopts = --reuse-db
--nomigrations를 사용할 경우 django migrations와 모든 모델 클래스 검사를 위한 DB 생성을 수행하지 않음pytest.marker를 이용해 테스트 함수나 클래스에 메타 데이터를 쉽게 설정할 수 있음pytest.mark.django_dbpytest.mark.urlsdjango의 URLCONF을 직접 지정할 수 있음myapp.test_urlsrf : django.utils.RequestFactory 인스턴스middleware를 거치지 않고 바로 view로 연결되는 request를 만듬request.user가 없어서 별도로 부착을 해줘야 함from myapp.views import my_view
def test_details(rf, admin):
request = rf.get('/customer/details')
# Remember that when using RequestFactory, the request does not pass
# through middleware. If your view expects fields such as request.user
# to be set, you need to set them explicitly.
# The following line sets request.user to an admin user.
request.user = admin
response = my_view(request)
assert response.status_code == 200
client : django.test.Client 인스턴스def test_with_client(client):
response = client.get('/')
assert response.content == 'Foobar'
Tip! 추가 내용

Tip! 추가 내용
$ pytest
test_*.py 또는 *_test.py 파일을 모두 실행root 경로에서 특정 디렉토리 내부의 테스트 파일을 수행해야한다면, 아래와 같이 root 경로 기준 파일 위치를 입력하여 테스트 파일을 실행$ python -m pytest {디렉터리명}/{테스트파일명}.py
-k 옵션을 사용test_로 시작해야만 테스트 함수로 인식$ pytest {테스트파일명}.py -k {테스트함수명}
Failed건만 F로 출력하고 Passed건은 .으로 표시-v 옵션 추가 시에는 각 테스트 함수 실행 결과를 출력-v 옵션으로는 내용이 일부 생략될 수 있음-vv 옵션을 추가하면 -v 옵션보다 verbosity level을 높여 더 자세한 테스트 실행 결과를 출력Failed건에 대한 stdout, stderr 메세지는 캡쳐됨-s 옵션을 사용--capture=no의 shortcut이라고 볼 수 있음Passed건에 대해서도 stdout, stderr 메세지를 캡쳐하고 싶다면 --capture=tee-sys 옵션을 사용하면 됨short test summary info에 출력되는 테스트 결과에 대한 옵션N f E s x X p P a A -r 옵션 뒤에 붙이는 문자에 따라 short test summary info가 출력됨-rfE로 Failed와 Error건이 출력됩니다.-rA -ra Passed건 제외하고 모든 테스트 결과 출력-fEs Failed, Error, Skipped건 출력-rN Failed가 하나라도 발생할 때 테스트 수행을 멈추고 싶은 경우 -x 옵션을 사용Failed N건 일 때 테스트 수행을 멈추고 싶은 경우 --maxfail=N 옵션을 사용--collect-only 옵션을 사용JUnit XML 형식의 테스트 결과 리포트를 출력하기 위해 --junit-xml={디렉터리명}/{xml리포트파일명}.xml 옵션을 사용pytest 실행 후 Jenkins에서 빌드 후 조치로 Publish JUnit test result report에서 해당 xml 파일 맵핑 설정을 해두면, Jenkins 빌드 결과 Test Result 메뉴에서 테스트 결과를 확인 가능--color=yes 옵션을 사용하면 테스트 결과 출력 시, 색상을 입힐 수 있음Jenkins Console Output에서 테스트 결과 확인 시, Passed/Failed을 강조된 색상으로 확인할 수 있어 유용$ pytest -h
pytest -h 명령어로 그 외 옵션 확인 가능pytest.ini 파일에서 아래와 같이 테스트 파일로 인식할 파일 형태나 기본 실행할 명령어 옵션을 설정할 수 있음[pytest]
python_files = test_*.py *_tests.py check_*.py
addopts = -vv --maxfail=10