8퍼센트가 Python Django 코드의 테스트 케이스를 작성할 때 쓰는 팀 내부 가이드를 공개한 글이다. 네이밍 규칙부터 factory_boy 사용법, 객체 생성 위치에 따른 속도 차이, mock 과 시간 고정까지 실무에서 반복되는 결정들을 짧게 정리한다.
핵심 포인트- 클래스명은 TestCase 를 상속하면 끝에 TestCase 를 붙이고, 테스트 함수명은 test_ 뒤를 한글로 써서 주석을 대신한다.
- fixture 대신 가급적 factory_boy 를 쓴다. 모델 객체 생성 시 signal 이 호출되는데 signal 테스트가 아니라면 mute_signals 로 끄면 된다.
- 객체 생성 위치가 속도를 가른다. setUp 은 매 테스트마다 다시 만들지만 setUpTestData 는 한 번만 만든다.
- 읽기 전용으로만 쓰는 객체는 setUpTestData 에서 만들고, 나머지는 테스트 함수 안에서 필요한 것만 만드는 편이 빠르다.
- naive datetime 을 DateTimeField 에 넣을 때는 반드시 make_aware 로 time-zone-aware 객체로 바꾼 뒤에 할당한다.
상세 정리- 함수명 예시는 조건과 기대 동작을 한글로 이어 붙이는 식이다. 쿼리스트링이 없는 경우와 있는 경우처럼 분기를 이름에 담는다.
- mute_signals 는 데커레이터와 컨텍스트 매니저 두 방식 모두로 쓸 수 있다.
- fixture 는 정의한 모델 객체를 모든 테스트 시작 전에 만들어두는데, setUp 에서 factory 를 쓰면 그와 비슷하게 매번 생성돼 느려진다.
- 메서드 모킹은 unittest.mock.patch 를 쓰고 보통 테스트 메서드의 데커레이터로 붙인다.
- 한 클래스의 여러 메서드나 모든 메서드에서 같은 함수를 모킹해야 하면 start 와 stop 을 쓰는 편이 편하다.
- 특정 시점 테스트가 필요하면 freezegun 으로 현재 시간을 고정한다.
- 시간 고정도 가급적 데커레이터나 컨텍스트 매니저로 범위를 좁히는 것이 좋다.
- start 와 stop 으로 테스트 케이스 전체에 적용할 때는 반드시 stop 을 호출해야 다른 테스트 케이스의 시간 값에 영향을 주지 않는다.
왜 읽나Django 테스트를 쓰긴 쓰는데 팀 안에서 방식이 제각각인 상황에서, 그대로 가져다 쓸 수 있는 규칙 묶음을 짧게 제시하는 가이드.