본문 바로가기

[도서리뷰]

[도서리뷰] TDD에 대한 오해와 진실, TDD 이야기

반응형

책 정보

저자: 신정호, 박상오, 이규일, 전우균, 조건희

발행일: 2013년 11월 15일

페이지:  185


리뷰

외적 압박만의 이유로 TDD를 도입하면 단시간 안에 실패할 확률이 매우 높기 때문이다.

저자들이 TDD를 현업에서 오랫동안 적용해보고 경험한 내용들을 정리한 책이다. 

모든 소제목에 난이도 1~5까지 측정되어 있으며, 책을 굳이 순서대로 읽을 필요없이 편한대로 읽어도 되게 구성되어 있다. 

생각지도 못한 부분도 있으며, 올해부터 TDD를 적용하고 있는 초보자로서 한번씩 고민했던 문제들에 대한 내용도 서술되어 있어 많은 도움이 되었다. 

평점: 4/5


내용

책은 크게 5장으로 나뉜다.

  1. 반가워 TDD
  2. TDD에 관한 오해와 진실
  3. 현장이야기
  4. TDD, 올바른 사용과 사용 습관
  5. 마틴 파울러의 "Mock은 Stub이 아니다"

 

이 책에서는 TDD를 다음과 같이 정의하고 있다.

  • TDD는 소프트웨어 개발 방법론 중 하나로, 테스트 주도 개발 방법론이다.
  • 테스트 코드를 먼저 작성함으로서 테스트 코드가 개발을 주도한다.
  • 테스트 코드가 개발을 주도하기 위해서는 반드시 실패를 포함하는 테스트 코드의 작성이 앞서야한다.
  • 앞서 작성된 테스트 코드를 통과할 수 있는 최소한의 구현 코드를 작성한다.
  • 최소한의 구현 코드는 개선될 수 있는 많은 여지를 포함하고 있는 코드다. 단지 테스트만 패스하면 된다.
  • 최소한의 구현 코드를 리팩토링 단계에서 개선한다.
  • 테스트 코드 작성 > 최소한의 구현 코드 작성 > 구현 코드에 대한 리팩토링 순으로 짧은 주기를 반복하며 점증적으로 개발한다.

마지막 정의, 테스트 코드 작성 > 최소한의 구현 코드 작성 > 구현 코드에 대한 리팩토링 은 어느 TDD 책이나 강의를 봐도 찾을 수 있는 내용이다.

 

이번에는 TDD를 도입하면서 겪었던 경험을 기준으로 내용을 정리해보자.

1. TDD를 왜하는가?

개발자로서 TDD를 왜할까...사실 단위,통합, 더 나아가 인수테스트까지 할 수 있다면 이것만 하면 되는거 아닌가? 

본인도 테스트의 중요성을 알면서 귀찮음에 차마 테스트코드를 작성 안하고 있었다. Postman으로 API 테스트해서 통과되면 그만 아닌가?

그렇게 해서 쌓인 레거시 코드가 어느날 정신차리니 너무 많아졌다. 

이러다 보니 오랜 시간뒤에 레거시 코드를 고치려하면 그 코드의 영향도를 파악할 수 없어 계속 기피하려는 자신을 발견할 수 있다. 

+ 정리되지 않은 코드는 이해하기도 어렵다.

 

이 책에서는 TDD를 하는 이유가 두가지라고 한다.

  1. 자질 향상: 프로그래밍을 잘하기 위해서, 결함을 없애기 위해서, 마인드를 변화시키기 위해서
  2. 외부의 압박: 정량적인 데이터가 인사평가에 적용되기 때문에, 동료가 하고 있어서

2번 외부의 압박 때문에 TDD를 하고 있다면 책에서는 그만두라고 권하고 있다. 

마치 친구따라 강남 놀러가듯이 TDD를 하게 되면 오히려 TDD의 목적이 변질될 수 있다.

특히나 코드 커버리지라는 목적을 두고 개발을 하게 되면 잘못된 방향으로 테스트를 하게 될수도 있다. 보통 좋은 품질의 코드라고 한다면 구문(Statement), 조건(Condition), 결과(Decision)에 대한 경우의 수를 모두 도출하고 수행되었는지를 판단해야하는데, 개발자의 경우 자칫해서 구문으로만 판단하게되는 참사가 벌어질 수 있다. 즉, 내 코드는 정상으로 돌아가! 라고 테스트하는 클린 테스트만 하게 되는거다. 

더 나아가 완벽한 코드는 당연히 존재할 수 없다. 분명 버그는 발생할 수 있고 수정해야하는 상황이 올텐데, 테스트를 진행하지 않은 경우에는 테스트와 배포 과정에서 변경에 대한 비용이 많이 발생한 다는것을 모두가 알거다. 하지만 테스트를 먼저 만들고 테스트 코드가 누적되었다면 이전에 테스트했던 사항이 얼만큼 영향을 미치는지도 확인할 수 있다.

여기서 짚고 넘어갈게 있다. TDD와 Unit Testing은 엄밀히 말하면 다른 녀석들이다. TDD는 목표를 미리 정하고 목적 코드를 작성하는 방법론이고 Unit Testing은 내 코드가 의도된대로 동작하는지 검증하는 절차다.

2. Private Method도 테스트해야하는가?

이 책에서는 역으로 private method에 대한 리팩토링의 냄새를 의심해보라고 한다. 

  • private method가 너무 비대하거나 복잡하지 않은가?
  • private method가 중요한 로직을 담고 있는가?

위와 같은 의심을 해봤다면, 해당 method는 퍼블릭 혹은 다른 클래스로 분리해야하지 않나 고민해야한다고 한다. JUnit의 홈페이지의 FAQ에도 비슷한 답변이 있다. (링크)

private 메서드를 테스팅 한다는 것은 다른 클래스로 이동해야 한다는 조짐일 수도 있습니다. 
(Testing private methods may be an indication that those methods should be moved into another class to promote reusability.)

private method를 왜 테스트 하고 싶어할까?를 생각해보면 구현체의 결함을 찾거나 개선하기 위해서다. 

그럼 왜 private으로 선언했을까를 고민해보면 세부적인 구현 내용을 공개하지 않는 선에서 캡슐화를 만족시키려 했을거다.

그래서 책에서는 가장 쉬운 방법으로 테스트하지 말라고 한다.

그럼에도 하고 싶다면 세가지 방법을 소개해준다

  1. 목적 코드의 private 접근자를 public으로 접근자로 변경 후 테스팅
  2. package private 접근자로 변경후 테스팅
  3. reflection을 이용한 테스팅

3. 바보 단계 거치기

이 부분은 사실 생각도 안하고 있었다가...내 뇌리에 스쳐간 코드가 너무 많아서 정리한다.

대부분의 개발자들은 목표하는 코드를 머릿속으로 디자인하고 개발을 시작한다. 이러한 과정에서 분명 바보 같은 모습의 코드도 포함되는 경우가 있을거다. 최종적으로 바보같은 코드가 되면 이후에 부끄러울 것이고 중간 과정이라면 전혀 부끄러워 할 필요가 없다고 한다.

페어 프로그래밍을 하게 된다면 당연히 냄새나는 코드를 꺼리게 될텐데, 오히려 바보 같은 코드는 개발 속도를 높이고 정신 건강에 이롭다고 한다. 

여기서 말한 바보 코드는 우리가 흔히 말하는 리팩토링이 필요한 냄새나는 코드다. 예를 들어 중복코드, 들쑥날쑥한 추상화, 의도를 나타내지 못하는 이름, 불필요한 로그 등.

위에서도 언급했듯이 TDD는 어차피 테스트 코드 작성 > 코드 구현 > 리팩토링의 짧은 순으로 돌아가는 방법론이다.

요구사항을 만족시키는 코드 (바보 코드)를 최대한 빠르게 작성해서 클라에게 제공을 해준다. 여기서 이미 클라의 관점에서는 기대를 충족시킨 상태로 우리는 테스트 케이스가 깨지지 않는지 확인하며 리팩토링을 진행하면 된다. 

4.  Top-Down으로 방향을 잡고, Bottom-Up으로 구현에 집중

개발자는 구현단위가 명확하고 구체적인 것을 좋아한다. 그런데 테스트를 제시하고 이를 빠른 시간안에 통과하려는 TDD를 접목하게 되면 구현체를 최대한 작은 단위로 구현하게끔 시야가 좁아지는 경향이 있다. 그러다보니 너무 큰 요구사항에 대한 부담을 느끼고 더 구체적인 요구사항을 찾으려고한다. 

그러한 단점을 보완하기 위해 Top-Down 방식으로 큰 시나리오를 작성하고 Bottom-Up 형태로 기능에 대한 코드를 구현하면서 문제를 차례 차례 해결해나가면 된다고 한다.

728x90