앞 장들이 “테스트를 어떻게 쓰는가”였다면, 이 장은 그 테스트를 실행하는 프레임워크의 부품들을 다룬다. 21장~24장에서 파이썬으로 직접 만든 xUnit이 바로 이 부품들의 조립체였다. 여기서는 그 부품 각각을 패턴으로 정리한다.
결과를 검증하는 최소 단위
단언(Assert). 테스트의 판정은 사람의 눈이 아니라 불리언 식으로 한다. 참이어야 할 것을 assertTrue로, 같아야 할 것을 assertEquals로 단언한다. 단언이 실패하면 프레임워크가 그 지점을 실패로 기록한다. 좋은 단언은 실패했을 때 “무엇을 기대했고 무엇을 받았는지”를 함께 알려 준다 — 그래서 assertTrue(a == b)보다 assertEquals(a, b)가 낫다.
판단 기준: 실패 메시지만 보고 원인을 짐작할 수 있으면 좋은 단언이다. 함정: 한 테스트에 단언을 잔뜩 쌓으면 첫 실패에서 멈춰 뒤쪽 단언은 검증되지 못한다 — 독립적 검증은 테스트를 나눈다.
공통 준비를 뽑아낸다
픽스처(Fixture). 여러 테스트가 같은 준비 코드를 공유하면, 그 준비를 setUp 메서드로 뽑아낸다. 프레임워크는 각 테스트 실행 직전에 setUp을 새로 호출해, 모든 테스트가 갓 만들어진 동일한 출발점에서 시작하게 한다. 이것이 25장의 격리된 테스트를 실현하는 장치다 — 상태를 매번 새로 만드니 테스트끼리 오염되지 않는다.
class MoneyTest(unittest.TestCase):
def setUp(self): # 각 테스트 직전에 새로 호출된다
self.five = Money.dollar(5)
def test_multiplication(self):
assert self.five.times(2) == Money.dollar(10)외부 픽스처. 준비 과정에서 파일·소켓·DB 연결처럼 외부 자원을 잡았다면, tearDown에서 반드시 되돌려 놓는다. 테스트가 실패해도 정리는 실행되어야 하므로, 프레임워크는 tearDown을 보장 호출한다. 얻은 것은 반납한다는 원칙이다.
판단 기준: 두 테스트 이상이 같은 준비를 반복하면 픽스처로 올릴 때다. 함정: 픽스처에 이 테스트 저 테스트가 조금씩 쓰는 걸 다 몰아넣으면, 각 테스트가 자기와 무관한 준비까지 짊어져 의도가 흐려진다 — 공유되는 것만 픽스처에 둔다.
테스트 하나의 규약
테스트 메서드. 테스트 하나는 이름 있는 메서드 하나다. 이름은 무엇을 검증하는지 서술하고(test_multiplication), 본문은 준비-실행-검증의 흐름을 담는다. 프레임워크는 정해진 접두어(test)나 어노테이션(@Test)으로 어느 메서드가 테스트인지 찾아낸다. 이름 하나하나가 명세의 항목이 된다.
예외 테스트. 정상 결과뿐 아니라 “예외가 던져져야 함”도 검증 대상이다. 기대한 예외가 나면 통과, 안 나면 실패로 뒤집어 단언한다.
@Test
public void testInsufficientFunds() {
assertThrows(InsufficientFundsException.class,
() -> account.withdraw(1000)); // 예외가 나야 통과
}예외 테스트는 24장에서 프레임워크가 실패를 잡아 기록하는 방식과 짝을 이룬다. 테스트 안에서 던진 예외를 프레임워크가 삼켜 실패로 집계하니, 한 테스트가 터져도 나머지 테스트는 계속 돈다. 이 격리가 있어 전체 테스트를 안심하고 한 번에 돌릴 수 있다.
판단 기준: 오류 경로도 정상 경로만큼 테스트할 가치가 있다 — 특히 사용자에게 보이는 실패라면. 함정: try/catch로 예외를 삼키고 catch 블록에서 아무 단언도 안 하면, 예외가 안 나도 테스트가 통과해 버린다. 예외가 “안 났을 때 실패”하도록 fail()을 넣거나 assertThrows를 쓴다.
한 번에 다 돌린다
전체 테스트. 모든 테스트를 명령 하나로 한꺼번에 돌릴 수 있어야 한다. 개별 테스트는 격리돼 있지만, 이들을 스위트로 묶어 통째로 실행하는 것이 통합에 대한 신뢰를 준다. 돌리기 번거로운 테스트 묶음은 결국 안 돌리는 묶음이 된다 — 클린코드의 환경 휴리스틱(E2, 테스트도 한 단계로)과 같은 원칙이다.
판단 기준: 커밋 전에 전체 스위트를 눌러 초록을 확인하는 게 습관이 되면 통합 회귀가 새어 나가지 않는다. 함정: 느린 테스트를 전체 스위트에 섞어 두면 전체 실행이 무거워져 아무도 안 돌린다 — 느린 것은 별도 스위트로 분리한다.
정리
- xUnit의 부품은 단순하다 — 단언, 픽스처(setUp/tearDown), 테스트 메서드, 그리고 이들을 묶어 한 번에 돌리는 전체 테스트. 21장~24장에서 직접 만들며 이 단순함을 확인했다.
- 픽스처가 격리된 테스트(25장)를 떠받친다 — 매 테스트마다 상태를 새로 만들고 자원을 반납하니, 테스트끼리 오염되지 않는다.
- 정상 결과뿐 아니라 예외도 일급 검증 대상이다. 예외가 “안 났을 때 실패”하도록 단언을 세운다.
- 프레임워크를 이해하면 그 안에서 자유로워진다 — 어노테이션과 규약이 무엇을 보장하는지 알면, 테스트가 왜 그렇게 동작하는지 헤매지 않는다.
다음장으로 30장