2부를 print로 값을 눈으로 읽으며 시작했다. 도착한 곳에는 TestCase, TestResult, TestSuite가 있고, 이들은 서로를 테스트한다. 닭 없이 부화시켜야 했던 달걀이 이제 스스로 알을 낳는다.

부트스트래핑이 완성되는 순간

18장에서 “메서드가 불렸는가”를 print(test.wasRun)으로 확인했다. 지금은 그 자리를 이렇게 쓸 수 있다.

class TestCaseTest(TestCase):
    def setUp(self):
        self.result = TestResult()
 
    def testRunning(self):
        test = WasRun("testMethod")
        test.run(self.result)
        assert "1 run, 0 failed" == self.result.summary()
 
    def testFailedResult(self):
        test = WasRun("testBrokenMethod")
        test.run(self.result)
        assert "1 run, 1 failed" == self.result.summary()
 
suite = TestSuite()
suite.add(TestCaseTest("testRunning"))
suite.add(TestCaseTest("testFailedResult"))
result = TestResult()
suite.run(result)
print(result.summary())

TestCaseTestTestCase를 상속한다는 데 주목한다 — 프레임워크가 자기 자신의 기능으로 자기 자신을 검증한다. print는 마지막 요약 한 줄에만 남고, 실제 판정은 전부 assert가 한다. 부트스트래핑이 닫혔다. 이 시점부터 xUnit은 자기 발로 선다.

xUnit의 구조

classDiagram
    class TestCase {
        +name
        +setUp()
        +tearDown()
        +run(result)
    }
    class TestSuite {
        +tests
        +add(test)
        +run(result)
    }
    class TestResult {
        +runCount
        +errorCount
        +testStarted()
        +testFailed()
        +summary()
    }
    class WasRun {
        +log
        +testMethod()
    }
    TestCase <|-- WasRun : 상속
    TestSuite o-- TestCase : 담는다(컴포지트)
    TestCase ..> TestResult : 기록한다
    TestSuite ..> TestResult : 공유한다

핵심은 세 갈래다. TestCase가 setUp → 본문 → tearDown의 실행 뼈대(템플릿 메서드)를 쥐고, TestSuite가 낱개와 묶음을 같은 run(result)로 다루며(컴포지트), TestResult가 성패 집계를 홀로 맡는다(책임 분리). 이 셋이 오늘날 거의 모든 언어의 테스트 프레임워크가 공유하는 골격이다.

2부가 남긴 것

  • 아주 작은 걸음. 검증 도구조차 없을 때도 “지금 확인 가능한 가장 작은 것”에서 시작했다. print 한 줄이 첫 초록이었다.
  • 로그 문자열로 협력 검증. 플래그 대신 "setUp testMethod tearDown "으로 순서를 증언하게 한 발상은 Self Shunt로 이어진다 — 테스트 대상이 스스로 자기가 받은 호출을 기록한다.
  • 하드코딩 후 중복 제거. 21장의 0 failed 상수를 22장에서 진짜 카운트로 바꾸는 리듬은 1부 Money의 return 10과 똑같다. 부가 달라도 리듬은 하나다.
  • 자기 참조의 검증. 프레임워크가 자기 기능으로 자기를 테스트하는 순간, 우리는 이 도구를 신뢰할 근거를 손에 쥔다.

판단 기준: 회고의 목적은 “무엇을 만들었나”가 아니라 “어떤 리듬이 반복됐나”를 보는 것이다. 2부의 모든 장은 1부와 같은 빨강-초록-리팩터링을, 단지 도구 없는 맨땅에서 반복했을 뿐이다.

다음장으로 25장