본문 바로가기

codeFacotry

실패하는 테스트 먼저

부끄럽게도 나는 테스트 코드를 많이 작성해 본 적이 없었다. 테스트는 "하면 좋은 것" 정도로 생각했고, 관련 개념도 깊게 알지 못했다. 최근 부트캠프를 진행하면서 첫 주제는 테스트 코드 작성에 관한 내용이었다. 관련된 세션을 듣고 테스트 코드에 대하여 배우면서 나의 마음에 픽된 한마디가 있었다. '실패하는 테스트 먼저' 이다. '실패는 성공의 어머니' 같은 뜻인가? 이런 아리송한 마음과 이상하게 내 마음을 뜨겁게 달군 '실패하는 테스트 먼저'라는 문구를 같이 알아보려고 한다.

소프트웨어 엔지니어링의 거장인 켄트 벡(Kent Beck)이 TDD(테스트 주도 개발)의 가장 핵심적인 개발 절차이자 규칙으로  Red-Green-Refactor라는 리듬을 정립했는데  그것은 다음과 같다

· Red: 처음에는 컴파일조차 되지 않더라도, 실패하는 작은 테스트를 먼저 작성한다.
· Green: 무슨 짓을 해서라도(심지어 하드코딩을 하더라도) 최대한 빨리 테스트를 통과시킨다.
· Refactor: 테스트가 통과된 상태를 유지하면서, 올바른 코드를 만들기 위해 중복을 제거하고 구조를 개선한다.

 

Red-Green-Refactor
Red-Green-Refactor 과정 ai 생성이미지



'실패하는 테스트 먼저'라는 절차는 Red 과정에 해당하는데 컴파일? 컴파일이라고??

'실패하는 테스트 먼저'을 알아보기 전 실패에 대한 나의 오해와 TDD 안 실패에 대하여 알아보자
 
나는 Red 단계에 실패는 검증 과정을 실패 즉 코드는 실행되지만 기대값(Expected)과 실제 출력값(Actual)이 다른 상태와 런타임 에러(Runtime Error)만을 의미하는 줄 알았다. 하지만 Red 과정에 실패란 컴파일 에러(Compile Error)와 런타임 에러, 검증 실패를 모두 포함하며 이 중 컴파일 에러는 상당히 중요한 실패이다. 켄트 벡의 『Test-Driven Development: By Example』에서 제시하는 흐름은, 컴파일 에러를 하나씩 없애가며 골격을 채워나가는 방식이다. 클래스가 없다는 에러가 뜨면 클래스를 만들고, 메서드 시그니처가 맞지 않으면 시그니처를 만들고… 이렇게 컴파일러의 손을 잡고 에러를 따라가며 개발하기 때문에, 컴파일 에러는 중요한 실패 신호다.

실패에 대한 오해를 해결하고 실패에 대하여 알아봤다. 다시 Red 단계로 돌아가면

첫 번째 단계로 실행되는 Red 단계, 그렇다면 왜 먼저여야 할까?
이에 대한 답은 구현을 먼저 쓰고 나중에 테스트를 추가하는 것과는 결과적으로 전혀 다른 코드가 나온다는 TDD의 핵심 통찰을 통해 알 수 있다. 테스트를 먼저 작성하면 자연스럽게 사용자의 시점에서 코드를 바라보게 된다. 이 함수를 어떻게 호출하고 싶은가? 이러한 질문에 답하게 되다 보면 호출하는 쪽에 편의를 신경 쓰게 되고 호출하는 쪽에 편의가 먼저 결정되니 구현은 그 편의에 맞춰서 따라오게 된다. 그 결과 API가 깔끔해지고 결합도가 낮아지는 효과를 얻을 수 있다.

반면 구현을 먼저 작성하면 어떻게 구현할까를 먼저 생각하게 된다. 내부에 대한 구현이 외부 인터페이스를 끌고 가게 돼 버리고 그 후 테스트를 붙이자고 하면 점점 테스트하기 어려운 코드를 완성할 수 있다.

테스트 코드를 작성하는것만으로 부족하고 왜 실패를 경험해야할까?

테스트 코드를 구현보다 먼저 작성했는데 실패하지 않는다면 해당 테스트가 아무것도 검증하지 못하고 있다던가 잘못된 곳을 바라보고 있다는 것을 알 수 있다. 이러한 점이 테스트 코드에 대한 sanity check가 된다. 또한 변화의 시작점을 명확히 할 수 있다. 코드가 정말로 해당 그 동작 때문에 통과했는지 아니면 다른 이유로 통과했는지에 대한 구분이 가능하게 해준다.

실패하는 테스트를 먼저 작성했을경우 얻는 이점

1. 기능 목표 명확화 : 앞서 계속 언급한바와 같이 테스트를 먼저 작성한다는것은 이 코드가 무엇을 해야하는지 미리 알수있다.
2. 필요한 코드만 작성 :  컴파일 에러를 잡아가며 개발하기 때문에 필요하지않을까? 하는 형식에 기능 구현을 방지 할수있다.
3. 조기 피드백 : 기능 구현전 테스트 코드 작성 중 버그를 수정하게된다면 기능 구현 이후 발생할 때보다 작업에 들이는 공수를  줄일수 있다.

실패하는 테스트 먼저 라는 말이 무엇인가에 대해 알아보고 왜 이런 주장이 나오는지에 대하여 알아봤다.
이 문구를 알아보고 공부하는 과정에서 내가 오해한 부분과 이해되지않았던 부분들을 해결하고 알아가면서 정말 재미있는 내용이고 또 막연하게 알았던 내용을 어느정도 알아간거 같아 기쁜 마음이 들었다.

앞으로는 모르는것을 부끄러워하지않고 그러한 부분을 채워나갈수있는 개발자가 되도록 노력해야겠다.