TotT: 변경 감지 테스트는 악몽입니다
원문: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html (Translated by Google Gemini)
당신은 방금 코드의 동작을 수정하지 않고 리팩토링을 마쳤습니다. 그리고 커밋하기 전에 테스트를 실행했는데… 수많은 단위 테스트가 실패합니다. 실패한 테스트들을 고치면서, 당신은 여러 테스트에 동일한 변환 작업을 기계적으로 적용하며 시간을 낭비하고 있다는 느낌을 받습니다. 아마도 당신은 어떤 메서드에 파라미터를 하나 추가했고, 이제 테스트 코드에 있는 100개의 해당 메서드 호출부에 빈 문자열을 전달하도록 업데이트해야 하는 상황일 겁니다.
테스트를 기계적으로 작성한다는 것은 어떤 모습일까요? 여기 터무니없지만 명확한 예시가 있습니다:
// 프로덕션 코드:
def abs(i: Int)
return (i < 0) ? i * -1 : i
// 테스트 코드:
for (line: String in File(prod_source).read_lines())
switch (line.number)
1: assert line.content equals "def abs(i: Int)"
2: assert line.content equals " return (i < 0) ? i * -1 : i"
이 테스트는 명백히 유용하지 않습니다. 이 테스트는 테스트 대상 코드의 정확한 복사본을 포함하고 있으며 체크섬(checksum)처럼 동작합니다. 테스트 자체가 테스트 대상 코드의 파생물이라면, 올바른 프로그램이든 잘못된 프로그램이든 테스트를 통과할 확률은 동일합니다.
실제로 아무도 저런 식으로 테스트를 작성하지는 않겠지만, 다음 예시와는 얼마나 다를까요?
// 프로덕션 코드:
def process(w: Work)
firstPart.process(w)
secondPart.process(w)
// 테스트 코드:
part1 = mock(FirstPart)
part2 = mock(SecondPart)
w = Work()
Processor(part1, part2).process(w)
verify_in_order
was_called part1.process(w)
was_called part2.process(w)
이런 테스트는 별다른 생각 없이 작성할 수 있고 빠르게 실행되기 때문에 작성하고 싶은 유혹이 듭니다. 이것이 바로 변경 감지 테스트(change-detector test) 입니다. 이 테스트는 테스트 대상 코드에 있는 동일한 정보의 변형일 뿐이며, 원본이나 수정된 프로덕션 코드의 올바른 동작을 검증하지 않은 채 프로덕션 코드에 어떤 변경이라도 가해지면 깨집니다.
변경 감지 테스트는 부정적인 가치(- value)를 제공합니다. 테스트가 어떤 결함도 잡아내지 못하면서, 추가적인 유지보수 비용이 개발 속도를 늦추기 때문입니다. 이러한 테스트는 다시 작성되거나 삭제되어야 합니다.