지금까지 테스트의 결과는 print로 값을 찍어 눈으로 읽었다. 하지만 테스트가 수백 개가 되면 사람이 일일이 읽을 수 없다. 필요한 건 딱 한 줄이다 — “몇 개 돌렸고 몇 개 실패했는가”. 초록/빨강 막대 아래 늘 붙어 있는 그 요약. 그걸 만들 차례다.

결과를 담는 객체 TestResult

카운트를 어디에 둘까. TestCase 안에 두면 각 테스트가 자기 카운트만 알아 전체 집계를 못 한다. 그래서 결과를 별도 객체 TestResult로 분리한다. run()이 실행되며 TestResult에 “나 시작했다”(testStarted)를 통지하고, 끝나면 그 객체가 summary()"1 run, 0 failed"를 돌려준다. 결과를 담는 책임을 테스트 실행에서 떼어내는 이 분리가, 다음 장에서 실패 개수를 세는 자리를 미리 마련해 준다.

판단 기준: 여러 테스트에 걸친 집계는 실행 주체(TestCase)가 아니라 전용 결과 객체(TestResult)에 모은다 — 책임이 갈라져야 확장이 쉽다. 함정: 카운트를 TestCase의 인스턴스 변수로 두면 테스트마다 흩어져 총합을 낼 수 없다.

Refactoring Step 20장 끝 상태 — run은 아무것도 돌려주지 않는다
1/3
class TestCase:    def __init__(self, name):        self.name = name    def setUp(self): pass    def tearDown(self): pass    def run(self):        self.setUp()        method = getattr(self, self.name)        method()        self.tearDown()class WasRun(TestCase):    def setUp(self):        self.log = "setUp "    def testMethod(self):        self.log = self.log + "testMethod "    def tearDown(self):        self.log = self.log + "tearDown "test = WasRun("testMethod")test.run()print(test.log)

summary()0 failed가 지금은 하드코딩이다. 1장에서 배운 그 죄악이다 — 아직 실패를 세는 테스트가 없으니 상수로 박아 초록을 만들고, 다음 장에서 이 중복을 지운다. runCount는 진짜로 세지만 failed는 아직 가짜다. 이 비대칭이 다음 장이 풀 숙제를 정확히 가리킨다.

이 장이 남긴 할 일 목록

  • 수집된 결과 출력하기 부분적으로 — run만 진짜
  • 실패한 테스트 세기 — 0 failed가 하드코딩
  • 여러 테스트 실행하기

판단 기준: run은 세지만 failed는 하드코딩 상수로 남겼다. 아직 실패를 만들어내는 테스트가 없어 실패 카운트를 검증할 방법이 없기 때문이다 — 검증할 수 없는 코드는 진짜로 만들지 않는다.

다음장으로 22장