프레임워크의 존재 이유는 결국 이것이다 — 테스트가 실패했을 때 그 사실을 알려 주는 것. 그런데 21장의 run은 테스트 메서드가 예외를 던지면 그대로 같이 죽는다. 예외가 run을 뚫고 올라와 프로그램을 멈춘다. 그러면 실패를 세기는커녕 요약조차 못 낸다. 실패를 잡아 “실패 1건”으로 기록하고 다음으로 넘어가는 것 — 이게 이 장의 일이다.
실패는 잡아서 세는 것이지 터지는 게 아니다
해법은 try/except다. 테스트 메서드 호출을 try로 감싸고, 예외가 나면 except에서 result.testFailed()를 불러 실패 카운트를 올린다. 예외는 거기서 멈추고 프레임워크는 살아남는다. 이 구조가 있어야 21장에서 하드코딩으로 남겨 둔 0 failed를 진짜 카운트로 바꿀 수 있다 — 이제 실패를 만들어내는 테스트(testBrokenMethod)를 쓸 수 있으니, failureCount를 검증할 방법이 생겼다.
판단 기준: 실패는 프레임워크가 잡아 “데이터”로 기록해야 할 정상 흐름이지, 프레임워크를 멈추는 예외 상황이 아니다. 함정: try 범위를 너무 넓게 잡아 setUp까지 감싸면, 준비 단계의 오류와 테스트 본문의 실패가 뭉뚱그려진다 — 우선 테스트 본문의 실패부터 정확히 잡는다.
class TestResult: def __init__(self): self.runCount = 0 def testStarted(self): self.runCount = self.runCount + 1 def summary(self): return "%d run, 0 failed" % self.runCountclass TestCase: def __init__(self, name): self.name = name def run(self): result = TestResult() result.testStarted() self.setUp() method = getattr(self, self.name) method() self.tearDown() return result# failed는 상수 0. testBrokenMethod가 예외를 던지면 run을 뚫고 나가 프로그램이 죽는다.
두 번째 스텝에 testFailedResultFormatting에 해당하는 검증이 숨어 있다 — 실패를 한 건 만들고 summary()가 "1 run, 1 failed"라는 정확한 문자열을 내는지 확인하는 것. 21장의 하드코딩 0이 이제 errorCount라는 실제 값으로 대체되면서 그 중복이 사라졌다. 예외를 뭉뚱그려 잡는 except:는 거칠지만, 지금은 “실패를 잡아 세고 살아남는다”는 골격을 세우는 게 먼저다. 어떤 예외였는지 기록하는 정교함은 나중 몫이다.
이 장이 남긴 할 일 목록
실패한 테스트 세기테스트 메서드가 실패해도 tearDown 부르기— try 밖에 두어 항상 불린다- 여러 테스트 실행하기
- setUp에서 난 오류도 잡아 기록하기
판단 기준: tearDown을 try/except 밖에 두어, 테스트 본문이 실패해도 뒷정리는 항상 실행되게 했다 — 20장이 목록에 남겨둔 “실패해도 tearDown 부르기”가 이 배치로 함께 해결됐다.
다음장으로 23장