18장에서 TestCase.run()은 이름으로 테스트 메서드를 부를 수 있게 됐다. 하지만 진짜 테스트는 메서드만 부른다고 끝나지 않는다. 대개 실행 전에 재료를 차려야 한다 — 객체를 만들고, 연결을 열고, 데이터를 심는다. 이 “상 차리기”를 매 테스트가 각자 하면 준비 코드가 중복되고, 더 나쁘게는 앞 테스트가 남긴 찌꺼기가 다음 테스트로 샌다.

테스트는 서로를 몰라야 한다

TDD가 겁 없이 굴러가는 이유는 각 테스트가 독립적이기 때문이다. 테스트 A가 실패했을 때 원인이 A 안에 있다고 믿을 수 있어야 한다. 만약 A의 성패가 B를 먼저 돌렸는지에 달려 있다면, 실패는 미궁이 된다. 그래서 프레임워크는 매 테스트를 깨끗한 상태에서 시작하도록 보장해야 한다. 그 보장 지점이 setUp이다 — 프레임워크가 테스트 메서드 직전에 반드시 불러 주는 준비 훅.

판단 기준: 준비 코드를 테스트 메서드 안에 두지 말고 setUp으로 뽑는 기준은 “이 준비가 매번 새로 필요한가”이다. 함정: 테스트끼리 상태를 공유해 준비 비용을 아끼려는 유혹 — 그 순간 독립성이 깨지고 실패 원인 추적이 불가능해진다.

setUp을 run이 먼저 부르게

검증 방법은 18장의 wasRun과 똑같은 수법을 쓴다. “setUp이 불렸는가”를 기록할 wasSetUp 플래그를 두고, setUp 안에서 켠다. 그러면 run()이 테스트 메서드보다 setUp을 먼저 불렀는지 관찰할 수 있다.

Refactoring Step 18장 끝 상태 — run은 테스트 메서드만 부른다
1/3
class TestCase:    def __init__(self, name):        self.name = name    def run(self):        method = getattr(self, self.name)        method()class WasRun(TestCase):    def __init__(self, name):        self.wasRun = None        TestCase.__init__(self, name)    def testMethod(self):        self.wasRun = 1test = WasRun("testMethod")test.run()print(test.wasRun)

TestCase에 빈 setUp을 둔 것이 핵심이다. 준비할 게 없는 테스트도 있으니 기본은 아무것도 안 하는 훅으로 두고, 필요하면 하위 클래스가 덮어쓴다. 이제 __init__에서 하던 wasRun 초기화도 사실은 setUp으로 옮길 수 있다 — 매 실행마다 깨끗이 리셋되는 자리가 바로 setUp이기 때문이다. 상 차리기의 자리가 생겼다.

이 장이 남긴 할 일 목록

  • setUp 먼저 부르기
  • 나중에 tearDown 부르기
  • 테스트 메서드가 실패해도 tearDown 부르기
  • 여러 테스트 실행하기
  • 수집된 결과 출력하기 (“5개 실행, 2개 실패”)

판단 기준: setUp만 초록으로 만들고 멈춘다. tearDown은 대칭적으로 필요해 보이지만 아직 실패하는 테스트가 없으니 손대지 않는다.

다음장으로 20장