[한글화 프로젝트] TDD는 죽었는가?
번역가 : 조인석 현재 중공업 필드에서 원격 플랜트의 주기기 모니터링 및 고장 예측 관련 업무를 수행하고 있다. 인공지능, 머신러닝 기반의 다양한 알고리즘과 인 메모리 기반의 Spark와 같은 빅 데이터 플랫폼 기술에 관심이 많다.
|
역자주 : 본 글은 Martin Fowler가 회의록 형태로 작성한 글로써, 세 화자가 나눈 대화를 1인칭 관점에서 작성한 것을, 독자 여러분의 이해와 번역 분량 축소를 위해 대화 형태로 변경하여 번역 하였습니다.
TDD는 죽었는가?
본 글은 Martin Fowler, Kent Beck, David Heinemeier Hansson과 함께 Test-Driven Development (TDD)와 TDD가 소프트웨어 설계에 미치는 영향에 관하여 나눈 대화입니다.
어디서부터 시작되었나
우리가 서로의 관점과 경험을 이해하기 위해 대화를 시작하게 된 것은 도발적인 발언과 블로그 포스트 때문이었습니다.
본 대화는 David가 Rails 커뮤니티에 TDD와 Unit Testing에 대한 언짢은 감정을 드러낸 David’s RailsConf keynote 로 인해 시작되었습니다. 그는 얼마 후에 몇 개의 블로그 포스트로 이어서 그의 견해를 정리했는데, 그 중 첫 번째 포스트가 바로 “TDD는 죽었다(TDD is dead)” 입니다.
며칠 후, 저는 후속 포스트에 대한 오탈자 내역을 보냈고, 그는 그의 발언과 블로그 포스트에 대해 내가 어떤 생각을 가지고 있는지 알고 싶다고 말하였습니다. 그 후 우리는 Skype를 통해 한 시간 동안 즐겁고 사려 깊은 토론을 하였습니다. David는 Kent와도 비슷한 토론을 하였고, Kent는 우리 세 명이 함께 토론을 하고 대화 내용을 공개하자고 제안하였습니다. David는 그 생각을 트위터에 올렸고, 많은 사람들이 긍정적인 반응을 보였습니다.
우리는 단지 30분씩 6번 정도의 가벼운 대화가 오고 갈 것이라고 생각했었지, 이 시리즈에 대해 별 다른 계획을 하지 않았습니다. 우리는 그저 서로의 경험과 관점에 대해 배우기를 원했기 때문에 이번 일을 시작하였습니다 - 실은 많은 사람들이 우리를 봐주기를 바라는 자아도취에 빠진 사람들 같았죠. 우리는 초반 에피소드에서는 질문을 거의 받지 않았습니다만, 마지막 에피소드에서는 몇 개의 질문에 답변을 주었습니다. 우리는 우리가 이 토론을 진행하는 동안 블로그와 트위터를 통해서도 토론이 지속 되는 것을 즐겼습니다.
비디오 셋업과 행아웃 시간대를 조정해 준 ThoughtWorks의 Wesley Clock에게 감사의 말씀을 전합니다. 저는 각 에피소드가 끝날 때 마다 토론 내용을 그저 지켜보기 보다는 읽혀지기를 바라는 마음에 회의록을 작성하였습니다.
1: TDD와 확신
우리는 TDD의 흐름에 대한 가지각색의 경험들과 사람들이 TDD와 자가-테스팅 코드를 종종 혼동하는 점에 대해 이야기 하였습니다.
회의록
David는 TDD와 단위테스팅에 대한 3 가지 주요 이슈를 띄우면서 토론을 시작하였습니다: 1) TDD와 단위테스팅의 정의에 대한 혼란, 2) TDD 구조를 준수하기 위해 사용한 mock객체들로 인한 테스트로 인한 손실, 그리고 3) TDD의 붉은색/초록색/리팩토링 사이클이 그에게는 무용지물이라는 것입니다. 저는 이해를 돕기 위해 TDD 등의 기원이 뭔지 아는 게 좋겠다고 의견을 냈는데, 이는 역사를 아는 것이 유용하기 때문이었습니다. 이에 Kent는 TDD의 기원에 대해 설명해주었습니다. 그는 스몰톡에서 여러 테스트 방식을 실험하기 시작했고 자기 성격에 TDD가 잘 맞았다고 합니다.
Martin : 우리가 C3에서 처음 함께 일하기 시작한 때가 생각나는 군요. 우리는 TDD를 사용하지는 않았지만, 각 프로그래밍 에피소드는 코드와 테스트가 함께 제공되었다고 장담합니다.
Kent : 프로그래머들은 그들이 작성한 코드가 잘 동작하는 것에 확신을 가져야 마땅하며, TDD가 그렇게 만드는 방법 중 하나(유일하지는 않은)이죠.
David : 저는 프로그래머의 행복을 위한 Ruby의 설계 목적을 좋아하고, 테스트 코드를 가지기 전까지는 일이 끝나지 않았다는 개념에는 동의합니다. - 하지만 TDD와 같은 방식으로 테스트 코드를 갖는 것을 선호하지는 않습니다. 사람들은 서로 사고방식이 달라서 서로 다른 기술과 언어를 좋아한다고 생각하고 있으며, TDD를 자가-테스팅 코드에서 얻을 수 있는 확신과 TDD라는 개념이 합쳐지는 것을 좋아하지 않습니다.
Kent : 최근 페이스북의 해커톤에서 절반은 TDD가 가능하였으나, 절반은 그렇지 않았었죠. TDD가 가능한 코드에서는 즐겁게 작업을 하고 있다는 것을 느꼈지만, 다른 절반에서는 그렇지 못 하다는 것을 느꼈었습니다. 하지만 non-TDD 파트에서도 여전히 저는 재발(regression) 테스트와 짧은 피드백 루프를 사용하였습니다. 저는 두 스타일을 함께 쓰는 것에 대해 별 다른 문제가 없었으며, 마치 클래식 음악과 재즈 음악을 함께 연주하는 것과 같았죠. TDD는 제가 학창시절에 수학을 어떻게 배웠는지 기억하게 해주었습니다 - 항상 예제가 필요했죠.
David : TDD가 잘 적용하여 개발을 한적도 있지만, 대부분의 저의 작업은 TDD가 잘 적용되지 않았습니다 - 제 질문은 “TDD를 적용함으로써 생기는 희생을 기꺼이 감수하는 이유가 무엇인가?”이죠. 많은 사람들이, 특히 무거운 mock객체 생성(mocking)으로 인해 나쁜 트레이드 오프를 합니다.
Kent : 다음 질문에 대한 트레이드오프에 대해 얘기 해보죠: 테스트가 가능한 중간 결과를 만들어내는 것이 가치가 있는 가? 컴파일러를 예를 들어보죠, 중간 구문분석-트리가 훌륭한 테스트 지점을 만들어주고, 더 좋은 설계입니다. 하지만 mock 객체에 대한 David의 질문에는 이렇게 대답하고 싶군요. 저는 mock객체를 거의 사용하지 않으며, 테스트는 리팩토링을 더 쉽게 해주는 반면, 목 객체는 종종 리팩토링을 더 어렵게 한다는 점이 좀 걱정 됩니다.
Martin : 저는 서로 다른 것이 뒤 섞이는 부분에서 전문 용어로 두 가지 문제점이 있다고 생각합니다.: 1) 첫째, TDD에 대한 David의 비평은 Mock객체를 사용해야 할 적합한 케이스가 아닌데도, 모든 TDD에 무거운 Mock객체를 써야만 한다는 가정을 하고 있습니다.; 2) 둘째, 자가-테스팅 코드와 TDD에는 차이점이 있습니다. TDD는 자가-테스팅 코드를 얻기 위한 한 가지 방법입니다.
David : 저의 TDD에 대한 반응은 무거운 mock 객체 스타일의 TDD를 도덕적으로 해야 한다고 말하는 사람들을 보았기 때문이며, 독립적인 단위 테스트를 가능하게 하기 위하여 비효율적으로 설계한 수 많은 코드들을 봤기 때문이죠.
Martin : 미리 정해놓은 시간에 따라 본 세션을 종료하겠습니다. 다음 세션에서는
어떻게 TDD가 손실을 발생시키는지, 진짜 손실인지, 어떻게 손실 유무를 판단 할 수 있는 지에 대해 논의 하겠습니다.
더 읽을 거리
· 이번 논의를 시작하게 된 David의 대화 (RailsConf talk).
· David의 에세이 중 TDD는 죽었다(TDD is Dead) 와 테스트-유도 설계 손실(test-induced design damage).
· Martin Flower가 얘기하는 자가-테스팅 코드(self-testing code)와 TDD의 차이점
· Martin Flower의 단위테스트의 정의(defining unit tests).
2: 테스트로 인한 설계 손실
David는 TDD를 사용하는 것이 hexagonal rails 와 같은 것에 도달하게 한다는 것을 느꼈습니다. hexagonal rails라 함은 지나친 간접 참조(indirection)로 인한 복잡성 때문에 테스트로 인한 설계 손실이 발생하는 경우를 말합니다. Kent는 이러한 현상이 TDD로 인한 것이라기 보다는 설계 결정에 대한 품질에 의한 것이라고 생각합니다.
본 대화를 보기 전에 David가 염려하는 설계 손실에 대한 예제(the gist David prepared)를 먼저 보십시오. 무척 그리운 Jim Weirich*가 hexagonal architecture 으로의 시도에 대한 동영상(explores this approach to a hexagonal architecture)도 보는 것을 권장합니다.
* 역자주) Jim Weirich는 2014년 2월에 타계하신 분이어서 무척 그립다(much-missed)라는 표현이 쓰였습니다.
회의록
Martin : 자, 이 질문으로 토론을 시작해보죠. TDD가 설계 손실을 발생 시킬 수 있나요? 손실이 실제로 손실로 이어 지나요? 어떻게 설계가 손실을 입었다고 판단할 수 있나요?
David : 저는 이 코드 예제(the gist he posted earlier)를 통해 답을 드릴 수 있겠네요. 사람들이 수 많은 mock객체를 사용하는 TDD를 쓰기 때문에 도달하게 되는 아키텍처를 예로 들어 보겠습니다. 애플리케이션의 각 레이어는 엄격하게 분리되어 있습니다. 가령, 컨트롤러는 실제 모델, 데이터베이스, 혹은 요청/응답 사이클을 사용 없이 테스트 할 수 있습니다. 그리 구체적인 예제를 보여주지는 않았습니다만, 단독 테스트를 쉽게 만들기 위해 너무나도 많은 불필요한 간접참조와 지나친 복잡도가 필요합니다.
Kent : 테스트-유도 손실을 TDD 탓으로 돌리는 것은 마치 자동차가 옳지 않은 장소에 주차되어 있다고 해서 차를 비난 하는 것과 같습니다. David가 보여준 설계는 TDD 때문이 아니었죠, 실제 이슈는 이러한 간접참조가 경우에 따라서 모두 좋은 트릭이 될 수 있다는 것이며, 우리는 이것이 가치가 있는지 없는지에 대해 이해할 필요가 있습니다.
David : 그 부분에 동의하지 않습니다. TDD 말(혹은 자동차)에 한번 올라 타면, 매번 기괴하고도 흉물스러운 테스트를 하게끔 명확한 길로 인도하고 있어요.
Kent : 그 부분은 설계 결정 이죠. TDD는 설계에 점진적인 영향을 줍니다, 사람들은 그들의 테스트 커버리지율이 얼마나 되는지에 대한 사항에 대해서는 호불호가 갈리죠. David에게 묻겠습니다. gist 에서 보여준 어떠한 코드들이 시스템 구조를 어렵게 만드나요? (“누군가 신경 쓰는 무언가가 눈 앞에 있다면- 그때가 바로 문제가 되는 설계를 바꾸고 싶은 때입니다.)
David : 코드의 크기와 코드 변경 용이성간에는 명확한 상관관계가 있습니다. 이러한 모든 간접참조는 반드시 동기화가 되어야 하며, 10 라인의 코드가 60 라인의 코드보다 이해하기도 쉽고, 변경하기도 쉽죠. 간접참조의 모든 레이어는 높은 비용을 지불해야 합니다. TDD의 붉은색/초록색/리팩토링 흐름은 무척 중독성이 강하고 (Kent는 세상에서 가장 가난한 마약 중개업자임을 밝혔습니다.), 이 중독은 사람들이 좋지 못한 결정을 하게 만듭니다.
Martin : 저는 그 의견에 반대합니다. 이러한 상황 (이번 사례는 Rails)은 TDD 때문에 발생한 것이 아니라 hexagonal architecture의 핵심인 환경으로부터의 고립에 대한 바람에 의한 것이죠.
David : 사람들이 고립을 원하는 이유가 바로 TDD입니다. 고립에 대한 다양한 논쟁에 대해 들어왔고, 그 중에 테스팅을 위한 고립만이 의미가 있다는 것이죠. rails 애플리케이션을 커맨드-라인 애플리케이션으로 변경하는 건 터무니 없는 일이라고 생각하며, 비슷한 사례로 인-메모리 저장소와 웹 서비스 호출은 각각의 운영상 특징이 달라서 서로 교환할 수 없는 것과 같은 이치입니다. 이런 교환 가능성에 대한 꿈이 진짜 목적은 아닙니다. - 진짜 목적은 단독 테스팅이죠.
Kent : 인-메모리와 웹 서비스를 같은 걸로 대할 수 없다는 것에 동의합니다. (여러분은 아마도 분리했다고 생각 할 수 있지만, 정말로, 정말로 아닙니다. ) 실패 케이스가 서로 다르기 때문이죠. 요소들간의 경계는 무너지게 마련입니다. 질문은 “요소들간의 디커플링의 정도를 알아내는 데 얼마나 많은 시간을 할애하고 싶은가?”입니다. 10 라인 코드 내부의 응집도와 60 라인 코드 내부의 응집도도 서로 다르죠.
David : 그 의견에 동의합니다만, 응집도와 결합력은 언제나 대립됩니다. 좋은 응집도를 얻기 위한 결합력 상승의 대가는 대부분 가치가 있죠.
Kent : 외부 의존성을 제거하기 위해 다른 방법도 존재하며, 컴파일러와 같이 중간 결과를 활용 할 수도 있습니다. 설계 통찰이 필요한 간접참조는 테스트 하기가 어렵습니다만, 대부분 테스트 가능성을 높여주는 더 나은 설계를 하게 만드는 통찰을 찾는 것이 유용합니다.
David : 테스팅이 더 나은 설계를 만들어낼 수 있다는 것에는 동의합니다만, 저의 경험상 그렇지 못 한 경우도 잦았으며, 테스트 하기에는 좋지 않은 설계였습니다.
Kent : David 는 스스로에 대한 확신이 부족하군요, 오늘은 통찰을 볼 수 없을지도 모르겠습니다. 그러는 동안에도 앞으로 나아가기 위해 노력해야만 하고요. 하지만 당신의 낙관적인 시각 덕분에 우연히 나마 그러한 통찰들을 찾게 될 것입니다.
David : 저는 이런 상황을 “신앙적인 TDD”라 생각합니다 - 이러한 감정을 종종 느꼈습니다만, 존재하지 않는 이상적인 해결책을 찾지 못 할 때 빠지는 우울한 루프 안에 꼼짝없이 갇혀버렸었죠.
Kent : David는 TDD에 관해서 얘기하고 있지 않고 일반적인 소프트웨어 설계에 관하여 이야기하고 있군요, 당신의 문제는 TDD 때문이 아니라 어떻게 피드백을 받을 수 있느냐에 관한 문제라고 명확하게 말할 수 있습니다. 소프트웨어 설계에 관해 생각 해 봅시다. 좋은 설계 통찰로 인하여 얻을 수 있는 이득은 무척이나 크죠. 이러한 통찰을 얻는 다는 것은 당신의 작업 흐름에 관한 것이 아니라, 언제 일하고 언제 쉬고, 다른 장소로부터의 영향도를 파악하고 다른 사람들과 협업하는 방식에 대해 알아가는 것과 같습니다.
우리는 다음 번 주제를 통해 프로그래밍 중에 어떻게 피드백을 찾아낼 수 있는 지에 관한 트레이드오프에 관해 이야기 해보자고 말하면서 이번 세션을 마무리 하였습니다.
더 읽을 거리
· David의 염려하는 설계 손실에 대한 예제(David's gist). 이 gist는 Jim Weirich에 의한 대화(a talk by Jim Weirich)를 통해 주어진 hexagonal Rails 아키텍처의 탐구에 기초를 두고 있음.
· David 의 블로그 포스트 중 테스트-유도 설계 손실의 문제점에 대한 소개(introducing the problem of test-induced design damage).
· "hexagonal architecture" 라는 용어를 만든 Alistair Cockburn의 글(originally coined by Alistair Cockburn), “포트와 어댑터”로도 소수 알려져 있음.
· hexagonal Rails 아키텍처의 출현과 이를 사용하는데 있어서의 트레이드오프에 대한 Martin Flower의 글 (the nature of a hexagonal Rails architecture and trade-offs around using it).
3: 피드백과 QA
우리는 프로그램을 하는 동안 피드백을 받고 QA로써 개발자에게 피드백을 주는 다양한 방법에 대해 토론하였습니다.
회의록
Kent : TDD를 수반하는 의사결정은 트레이드오프에 관한 것입니다. “어떤 이상적인 세계에서는 우리의 프로그래밍 결정에 대하여 즉각적이고 틀림없는 피드백을 받기도 합니다.” … “내가 만든 모든 코드는 배포할 준비가 되었다면, 그 즉시 배포합니다.” 하지만 이러한 이상적인 상황은 현재 불가능하기 때문에, 질문은 바로 “이런 이상에서부터 얼마나 멀리 떨어져 있는가?” 라는 것이죠. 트레이드오프에 대한 여러 가지 제약 사항들을 나열해 보겠습니다.
· 빈번도: 얼마나 빨리 피드백을 받고 싶어 하나?
· 충실도: 얼마나 정확한 붉은색/초록색 신호를 원하나?
· 오버헤드: 얼마나 지불할 준비가 되어 있나?
· 수명: 이 소프트웨어의 라이프사이클은 어떤가? 시간과의 개연성이 얼마나 되는 가?
이 4개가 우리가 비교해 볼 필요가 있다고 생각하는 제약사항들입니다. 우리는 서로 동의하기 위해 이 행아웃에 참여하고 있는 것이 아닙니다 - 제 개인적인 목적은 단지 나의 아이디어를 건설적인 방식에서 멀찌감치 몰아내기 위해 준비 되어진 사람들에게 나의 의견을 명확하게 전달함으로써 서로의 트레이오프들에 대해 이해하는 것입니다.
Martin : 우리가 피드백을 받기 위해 살펴봐야 할 3가지에 대해 강조하고 싶습니다.
· 소프트웨어가 사용자에게 유용한 무언가를 하고 있나? 급여 계산과 같은 경우에는 테스트가 도움이 되지만, html 렌더링과 같은 경우에는 도움이 되지 않습니다.
· 내가 무언가를 망가뜨렸나? “이 부분에서 만큼은 자가-테스팅 코드는 마치 구세주이죠.” 저는 적어도 한번쯤은 모든 테스트가 실패하는 것을 보고 싶어요.
· 나의 코드-기반이 건강한가? 건강하다면 저는 빠르게 빌드를 계속 할 수 있습니다. 이 부분은 당신의 코드를 누가 인수 할지 명확하지 않을 때 더욱 까다로울 수 있습니다.
David : QA를 쓸모 없게 만드는데 TDD가 한 몫 했다는 주제를 제시하고 싶습니다. 많은 회사가 TDD를 택하고 QA을 없앴고, Basecamp는 2년 전까지만 하더라도 QA가 없었습니다. 저는 TDD가 프로그래머들이 “나는 QA가 없다는 것에 대해 무척 자랑스러워”라고 생각하게 만들었다고 생각하고 있었습니다. 오래된 모델이 제 기능을 동작하고 있지 못하고 있는 동안에, 시계 추는 너무나도 멀리 흔들리고 있었죠: “저는 당신이 물리적인 품질에 관한 어떤 작업도 수행 할 수 없다고 생각하며, 당신이 아닌 누군가가 테스트 하지 않는 한, 훌륭한 소프트웨어를 만들 수 없을 것이라고 생각합니다.” 저는 QA가 팀에 합류하는 것이 얼마나 강력한 힘을 발휘하는 지 보았기 때문에, 이러한 상황이 실망스러웠습니다.
David : 다른 이슈는 트레이드오프에 대해서 이해하려면 비용에 대해 반드시 이해해야 하고, TDD에 대한 모든 이야기는 TDD로 인한 이득에 관한 이야기이라는 것이죠. 이 비용을 고려 하지 않는 것 때문에, 사람들은 테스트로 인한 손실이 있다는 것을 충분히 이해하지 못하는 겁니다. 신뢰성에 대한 비용을 생각해봅시다: 99%에서 99.999%로 가는 것은 99%에 머무르는 것보다 기하급수적으로 많은 비용을 필요로 합니다. 높은 신뢰성은 우주 왕복선이나 레이스의 선두주자들에게나 중요한 이야기지, 실험적인 웹 사이트에게는 필요가 없습니다. 운영환경에서 사용하는 코드는 테스트 코드 없이 작성하지 않는 다는 규칙과 시스템의 중요성과는 상관관계가 없다고 봐야 합니다. (역자주: 시스템이 중요하지 않다고 해서 운영환경의 소스 코드를 테스트 코드 없이 작동해도 된다라는 건 옳지 않다는 뜻이네요.)
Kent : QA 에 관한 이슈로 돌아가보죠, QA와의 오래된 관계는 제대로 동작하지 않는 다고 생각합니다. 제 사무실의 페이스북에서 들고 나온 포스터에는 “페이스북에서는 어떠한 것도 다른 누간가의 문제점이 될 수 없다.”라고 말하고 있으며, 페이스북이 회사의 규모에 비해서 이 말을 잘 지키고 있다고 느끼고 있습니다. 페이스북은 최근까지도 QA가 없었으며 프로그래머는 QA에 대한 책임까지 가지고 있었습니다. “그럼 무엇과 비교하실 건가요?” 라고 묻는 다면, 효과적인 QA를 가지는 것이 QA가 없는 것 보다는 낫지만, 과거의 제대로 동작하지 않는 관계라면 QA가 없는 것이 낫다고 생각합니다.
Martin : ThoughtWorks에서 일할 때 항상 QA가 있었습니다. 저도 역시 90년대와 비교해보면 잘 동작하지 않던 대립적인 관계도 사라졌고, 수작업으로 진행하던 스크립트 기반 테스트도 사라졌다는 것을 느끼고 있습니다. 그리고 스타트업들이 QA 없이 운영할 수 있는 건 그들 마음 이죠.
David : 초기 스피드를 위하여 심사숙고한 QA와의 트레이드오프에 대해서는 동의합니다만, 어떤 경우에는 프로그래머의 테스트가 지나칠 정도도 있어 왔으며, 실험적인 테스팅에서 어떠한 가치도 찾지 못 하기도 합니다. 만약 개발자들이 QA 없이도 충분히 높은 품질의 소프트웨어를 만들 수 있다면, 당신의 테스트들은 모두 초록색이겠지만, 운영환경에서의 사용자들은 당신이 예상하지 않았던 행동을 하게 마련이라는 거죠. 무엇보다 나쁜 것은 개발자들이 고객 서비스의 일부분이 아니라는 점입니다. 많은 프로그래머들은 단조롭고 지루하다는 이유로 전화 응대를 하고 싶어 하지 않습니다만, 그 또한 피드백 루프죠. 초록색 테스트를 통과한 코드는 당신이 원하는 범위 내에서는 안정기에 접어들었다고 할 수도 있습니다.
Kent : 이 제약사항에 관하여 다시 생각하기 위해 초록색 바 안에 빨간색 픽셀 몇 개를 심어야만 한다고 생각합니다. “전화 응대는 당신이 작성하지 않은 테스트를 가르쳐주기 위한 피드백 루프입니다.” 페이스북 프로그래머들은 전화응대를 해야만 하며, 모두들 그것에 대해 불평하고 있지만, 어느 누구도 전화응대를 피할 수는 없습니다. 당신이 더 이상 실수를 저지르지 않는다고 생각하는 그 순간, 그 것이 바로 실수이며, 당신은 성장 할 수 없습니다. 결국 “세상은 당신이 아무것도 망치지 않은 척 하게 내버려두지 않을 것입니다.” 저는 이른 새벽 2시에 받은 전화 한 통을 통해 꽤 값진 경험을 하였습니다.
Martin : 우리가 테스팅 비용에 관하여 더 이상 얘기하지 않는 것을 확인하고, 이번 세션을 마무리하였고, 다음 기회에 다시 한번 살펴 보자고 제안하였습니다. 또한 같은 주제로 Mike Bland가 제 사이트에 올린 글을 보는 것도 좋을 것이라고 언급하였습니다.
4: 테스팅 비용
우리는 테스팅과 TDD에 대한 덜 긍정적인 부분에 대해 토론하였습니다: 당신은 테스팅을 너무 지치게 하고 있지 않은가, 그리고 기능적인 코드보다 테스트에 더 많은 가치를 부여 하는 것이 팀에 문제가 되고 있는가?
회의록
David : 트레이드오프에 대해서 얘기하기 위해서는, 결점에 대해서 명확하게 이해하고 있어야만 합니다. 만약 결점이 없다면 트레이드오프도 없기 때문이죠. 저는 TDD가 어떤 것을 강제로 하라고 하지는 않지만, 명확한 방향으로 부추기고는 있습니다. 지나친 테스팅을 첫 번째 이슈로 얘기해보죠. 여러분은 결함 테스트가 없는 코드를 작성하면 안 된다는 얘기를 자주 듣죠, 처음에는 괜찮아 보입니다만, 지나친 테스팅을 하게 만들기도 합니다. 가령, 운영 코드의 매 라인을 위한 4 라인짜리 테스트 코드가 있는 것과 같은 것을 말하죠. 이 말은 당신이 무언가를 변경하려고 하면, 변경할 코드가 더 많아 진다는 뜻 입니다.
Kent : 사람들은 테스트 코드를 작성하기 위한 비용을 지불하는 것이 아니라, 충분히 확신을 하기 위해 작성하고 있는 것입니다.
David : 그럼 여러분(Kent와 Martin)은 운영 코드의 각 라인을 작성하기 전에 매번 테스트 코드를 작성하시나요?
Kent : 상황에 따라 다르죠, 그리고 이 대답은 흥미로운 질문들에 대한 모든 나의 답변의 시작부분과 같다고 할 수 있습니다. JUnit을 사용하는 운영 코드는 엄격하게 테스트 코드를 먼저 작성하게 되며, 이러한 과정 속에서 모습이 들어나는 자신의 모습(역자주 : 운영코드)으로 인해 무척이나 행복해합니다 - 그렇기 때문에 저는 TDD를 사용할 때 항상 지나친 테스팅을 하게 된다고 생각하지 않습니다.
Herb Derby : 델타 커버리지 개념에 대해 언급하고 싶군요 - 이러한 테스트는 중복되지 않는 비율이 얼마나 되나요? 제로 델타 커버리지 테스트는 그들이 의사소통 목적과 같은 것을 제공하지 않는 한, 제거되어야만 합니다. 저는 자주 system-y 테스트를 작성하고, 구현을 하며, 리팩토링을 거치고 나면, 결국 초기 테스트는 버려지게 되고 맙니다. 많은 사람들이 테스트들을 버리는 것에 대해 흥분하지만, 그들이 당신에게 아무것도 사주지 않는다면 당신도 흥분하게 될 것이라고도 했죠. 같은 것이 여러 방식으로 테스트 된다면, 그것이 바로 결합(커플링)이며 결합 비용이 발생합니다.
Martin : 지나친 테스트 코드는 분명 존재합니다, ThoughtWorks는 강한 테스팅 문화를 가지고 있기 때문에, ThoughtWorks에서도 발생하죠. 적정 수준의 테스트의 양을 정의하는 건 무척 어렵습니다. 어떨 때는 지나칠 때도 있고, 어떨 때는 적을 때도 있죠. 저는 가끔 지나치게 테스트하기를 원하며, 테스트가 너무 방대하지 않는 한 그렇게 하는 것에 있어 걱정하지 않습니다. 모든 라인의 코드를 테스트 하느냐라는 포인트에 대해서는 제가 다음 질문을 드리죠: “제가 이 코드를 망치는 것이 테스트를 실패하게 만드는 건가요?” 저는 때때로 고의로 코드 라인을 주석처리 하거나 조건을 반대로 바꾸고 나서 실패할 것이 확신한 테스트를 돌려보기도 합니다. 저의 반대쪽 머리의 (Kent로부터 온) 테스트는 그저 실패할 수도 있는 것들을 테스트하는 것입니다. 라이브러리들은 (정말 불안정하지 않는 한) 잘 동작한다고 가정합니다. 제가 라이브러리를 잘 못 사용하고 있는 지와 실수의 결과가 얼마나 심각한지 묻고 싶군요.
Kent : 테스트 코드 라인수와 운영 코드 라인수와의 비율은 믿기 어렵습니다. 저의 기억에 남는 경험은 Christopher Glaeser가 컴파일러를 작성하는 것을 보는 것이었으며, 그는 컴파일러 코드의 각 라인을 위한 4라인의 테스트 코드를 가지고 있었습니다. 간단한 시스템은 더욱 낮은 비율을 나타내겠죠.
David : 코드의 한 라인을 임시 주석 처리(comment out) 한 것이 눈에 띌 정도면 테스트 커버리지율이 100%라는 것을 의미합니다. 임시 주석 처리로 인한 소스 쪼개기가 어떤 경우에 값지다고 할 수 있는 지 생각해 봅시다. Rails의 선언적 주석문은 가치 있는 테스팅을 위하여 소스를 충분히 쪼개지 않습니다. 그렇기 때문에 저는 100% 이하의 커버리지율에도 충분히 만족합니다.
Martin : 만약 당신이 코드를 자신 있게 변경 할 수 없다면, 당신의 테스트는 (혹은 좋은 테스트) 충분하지 못 하다는 것을 의미합니다. 지나치다는 신호는 당신이 코드를 변경할 때, 코드를 변경하는 것 보다 테스트를 변경하는 노력이 더 많이 든다고 느낄 때를 말하는 거죠. 여러분은 Goldilocks zone* 안에 들어가길 원합니다만, 당신 혹은 당신의 팀이 어떠한 실수를 하는 경향이 있는 지와 누가 문제를 일으키지 않는 지에 대해 알아가는 경험과 함께 들어갈 수 있는 거죠. 저는 제가 확신이 없을 때 “코드의 한 라인을 임시 주석 처리 해도 되나” 라는 시도를 하는 것을 좋아하며, 그 시도가 시발점이지만, 그 환경에서 더 일하다 보면 더 나은 발견을 하게 됩니다.
* 역자주> Goldilocks zone은 태양계에서 생명체가 살기 적합한 영역을 말합니다.
David : 이러한 튜닝은 잘 모르는 팀과 함께 코드를 제어하고 더 많은 테스트가 필요로 하는 컨설팅 팀과 상대적으로 더 안정적인 운영팀에게는 서로 다른 것으로 느껴지는 군요.
Kent : 테스트 우선 원칙에 대해 배운 것이 좋았으며, 그건 마치 까다로운 개발을 위한 4륜자동차의 저단 기어와 비슷한 거죠.
David : 다음 이슈로 넘어가보죠: 많은 사람들이 코드보다 문서화가 더 중요하다고 생각하곤 합니다. 지금 제가 걱정하는 것은 사람들이 기능 코드보다 테스트를 더 중요하게 생각한다는 것이죠. 이 부분은 TDD 사이클의 리팩토링 파트가 강조하는 부분과 연결이 됩니다. 이러한 모든 것들이 코드를 리팩토링하고 깨끗하게 유지 하는 것에 충분하지도 않은 에너지를 쏟아 붓게 만듭니다.
Kent : 운영 코드임에도 불구하고 버려졌지만, 테스트를 계속하고 재구현한 사례가 있습니다. 저는 새로운 코드가 잘 동작하고 있다는 것을 알려주는 테스트를 무척이나 좋아합니다.
David : 한 가지 흥미로운 질문이 떠오르는 군요: 꽤 많은 코드를 버리고 테스트 코드를 유지한 적이 있나요? 아니면 반대 상황이 있었나요? 각 상황에 맞는 답을 주셨으면 합니다.
Kent : 저는 테스트 코드를 읽을 때 코드가 어떻게 동작하는 지 쉽게 이해할 수 있습니다. 둘 중에 무엇이 더 중요하다고 생각하지는 않습니다 - 가장 중요한 포인트는 테스트 코드와 기능 코드가 서로 맞지 않으면, 그 부분에 에러가 있다는 것을 더블 체크 하는 것입니다. 저도 때로는 테스트 코드가 종료를 의미하는 것이기 때문에, 팀들이 사용자를 지원하는 것 보다 테스팅 환경에 더 많은 에너지를 쓰는 좋지 않은 상황을 만들기에 David의 의견에 동의합니다. 저는 코드가 완성되었을 때의 쾌감도 즐기지만, 가장 스릴이 넘치는 부분은 새로운 기능을 추가 했을 때죠, 속임수로 보일 수도 있지만, 코드 작성이 쉬워집니다. 이 모든 것들이 클린 코드에 의한 것입니다만, 코드를 깨끗하게 유지하는 거 하고, 쾌감을 느끼는 것 하곤 차이가 있습니다.
Kent는 Jeff Eastman를 비유로 설명하였습니다. 지문으로 담기에는 한계가 있군요. 그는 큰 설계 단순화를 설명하기 시작했습니다. 그는 신규 테스트가 동작하게 하는 것의 가치를 설명하는 것은 쉬우나, 설계를 깨끗하게 유지하는 것의 가치를 설명하기에는 어렵다고 말하였습니다.
David : 사람들은 정량적인 것들에 집중하기 마련이지만, 설계 품질을 숫자로 표현 할 수 없습니다 - 해서 사람들은 테스트 속도, 테스트 커버리지율, 테스트 비율 등에 대한 것 들은 우선순위에서 밀려나는 거죠. 이러한 것들은 꿀 팁과 같죠, 우리는 이러한 것들의 싸이렌 소리에 귀 기울일 필요가 있습니다. 운영 코드보다 테스팅 환경에 더 신경 쓰게 되는 것에 대하여 생각할 필요가 있습니다. 이는 오로지 비기술적인 이해당사자들에게만 유용한 지표가 될 수 있습니다. TDD를 파는 것이 중요하곤 했지만, TDD는 모든 것을 정복했으며, 우리는 TDD의 단점에 대해 살펴 볼 필요가 있습니다.
Martin : 저는 TDD가 지배적인 위치에 있었다고 생각하지 않습니다. 아직도 TDD를 적용하려고 하는 곳도 많거든요.
더 읽을 거리
· 측정을 잘못하는 경우의 토픽을 위해서 Pat Kua의 다음 글을 읽어 보세요. an appropriate use of metrics.
· Martin Flower의 테스트 커버리지율의 사용법과 잘못된 사용법(use and misuse of test coverage).
5: Q&A
우리는 시청자들의 질문에 답변을 주었습니다: TDD의 오픈소스 예제는 무엇인가, 우리가 TDD를 사용하는 방법을 변경하게 만드는 변화가 무엇인가, TDD를 경험하지 못한 개발자에게 TDD를 잘 적용하게 하는 방법은 무엇인가. 우리는 TDD의 건제함에 대한 관점에 대해 정리하면서 마무리 하였습니다.
회의록
Martin : 시청자들이 올려 놓은 질문 중 일부에 답변을 드리겠습니다. David가 Mike Harris의 “TDD를 활용한 오픈소스 프로젝트는 어떤 것이 있으며, 테스트-유도 설계 손실 혹은 TDD를 잘 활용한 사례가 있는가”라는 질문에 답변을 드리는 걸로 본 세션을 시작하겠습니다.
David : 좋은 사례를 찾기 쉽지 않으며, 이 또한 논의 해볼만한 문제입니다. 우리에게는 일반적인 상황의 좋은 애플리케이션 사례가 없습니다. 왜냐하면 오픈소스 협력자들은 대개 개인적인 애플리케이션과 오픈소스 공통 프레임워크, 라이브러리들을 대상으로 작업하기 때문입니다. 다른 관점에서 이 논의의 결론을 내자면, 어떤 것이 실제로 의견충돌이 발생하는 것 보다 더 많은 의견충돌을 만들게 하는가에 대한 답이 필요합니다. 사람들은 철학적인 원칙보다는 실제 코드를 가지고 옵니다. 우리의 코드 예제는 사람들이 실제로 작업하고 있는 것에 비해서 그다지 중요하지 않습니다. 해서 당신은 설계 손실 설명을 위해 사용한 Jim Weirich의 예제를 위한 PT자료로 사람들을 이해해야만 합니다. 좋은 Rails 코드는 책에서 보여주는 표준 테스팅 방안에서 찾아 볼 수 있습니다.
Martin : 실제 코드를 이해하기 위해서는 많은 노력이 필요합니다. 저도 저희 팀의 코드 기반을 파고 들어가곤 합니다만, 무척 시간이 많이 걸리며, 팀과 일하는 경우 모두 같은 수준으로 이해하지 못합니다.
Kent : JUnit은 TDD를 엄격하게 사용하는 프로젝트 예제이며 잘 동작합니다. 하지만 이 논의의 좋은 예제로 들 수는 없겠군요. 왜냐하면 JUnit은 TDD를 위한 최고의 방안을 명확한 인터페이스를 통해 제공하기 때문입니다. 우리는 상이한 종류의 애플리케이션에 관해 얘기 하고 있습니다. 만약, 좋은 예제를 가지고 계신 분이 계시면, 꼭 내용을 공유해주시기 바랍니다.
David : 우리는 프로그래밍을 과학으로 대할 수 없습니다 - 우리는 기술을 객관적으로 평가 할 수 없습니다. 가치가 없는 논의를 하고 있다는 뜻은 아닙니다. 우리는 완전한 답을 얻을 수 없으며, 이치에 맞게 만드는 작업은 여러분의 몫입니다.
Kent : 동의합니다. 우리는 실험을 복제할 수는 없습니다만, 과학적인 사고방식으로 개개인이 바라볼 수는 있습니다. 우리는 우리 스스로 경험에 기반하여 시도해볼 수는 있겠습니다만, 일반적인 답변을 드릴 수는 없겠군요.
Martin : 다음 질문으로 넘어가겠습니다. Graham Lee님이 주신 질문입니다: Kent와 Martin에게 묻겠습니다. 소프트웨어 작성시 TDD를 사용하지 못 하게 하는 혹은 쓸모 없게 만드는 것은 무엇일까요? David에게는 이런 질문을 드리고 싶군요. 어떤 것이 TDD가 유용하게 동작하게 할 수 있을까요?
Kent : 제 포스트(RIP TDD post)를 한번 보시죠. TDD는 여러 문제점들을 해결하며, 확신을 갖기 시작하게 만듭니다. 또한 TDD는 문제점들을 작은 단위로 쪼개지게 해주며, 한번에 일반적인 문제를 해결하는 것 없이 구체적인 문제점을 걸고 넘어집니다. 저는 TDD가 단지 어렵다는 이유로 포기할 생각이 없습니다.
Martin : 저는 TDD를 쓸모 없게 만드는 것에 대해서 이야기 하기 보다는 다른 관점에서 TDD의 적용 가능성에 대해 말씀 드리겠습니다. 저는 훌륭한 설계를 우연히 접하였을 때 차분한 '신속한 느긋함'을 이용하여 기계적인 방식으로 TDD를 따르고 있습니다. 근래 대부분의 저의 프로그래밍은 제 웹 사이트 툴체인이며, 조금씩 진전이 있을 때마다 훌륭한 회귀 테스트가 딸려 있죠 - 저는 TDD 적용가능성을 찾지 못하였습니다. 하지만 제가 infodeck 코드를 빌드할 때면, TDD가 효과적이었던 애플리케이션이 있었습니다. 어떤 애플리케이션에서는 TDD가 무척 잘 들어 맞지만, 아닌 경우도 있습니다. 그리고 사람들은 그들의 성격을 애플리케이션에 반영하죠.
David : 제 경험도 비슷합니다. 저는 TDD를 통한 테스팅이 좋았고 모든 곳에 적용하려고 노력하였습니다만, MVC 웹 애플리케이션의 많은 영역에서는 TDD가 잘 맞지 않다는 것을 서서히 깨닫게 되었습니다. 이는 TDD가 어떤 상황에 대하여 효과적이 않다고 말씀 드리는 것이 아니고, 단지 제 작업의 작은 부분에 이런 사례가 있었다는 것입니다. 하지만 TDD를 사용하지 않게 되는 것이 자기-테스트 코드를 포기 하고 싶다는 것은 아닙니다 - 이것이 항상 저에게는TDD의 가치라고 생각합니다.
Martin : 제가 정확하게 TDD(혹은 어떤 기술)를 받아 들이는 방법을 알려드리겠습니다. 시험해 보고, 남용한 다음에, 여러분에게 잘 들어맞는 방식에 안착하세요. 그리고 조금 더 깊이 들여다보세요. “TDD는 자가-테스팅 코드를 향한 마약의 출입구입니다.”
Kent : 사람들은 결국 이러한 프로세스를 수행하는 작업 흐름을 가지게 됩니다. 제가 경험한 TDD는 David의 경험과는 다릅니다. 제가 개발할 때 어려운 부분을 만나게 되면, 저는 그 부분을 간단하게 만드는 명확한 체계를 가진 객체에 대한 아이디어를 얻습니다. TDD는 그러한 아이디어, 시도 그리고 API의 사용 예제와 구현 방법에 대한 피드백을 신속하게 가져다 주는 메커니즘을 제공합니다. 물론, TDD가 잘 맞지 않는 경우도 있죠. 그런 경우 command-R이 피드백을 받기 위한 좋은 방법인 것을 찾았습니다만, 그러한 순간에도 단순한 객체를 만들고 TDD를 시도하는 것을 원하기도 합니다.
Martin : Tudor Pavel님의 질문을 한번 볼까요? "경험이 적은 개발자들에게 TDD는 어떻게 동작합니까?" TDD는 사람들에게 작은 조각에 집중할 수 있게 강요하며, 인터페이스를 구현체로부터 분리하게 도와줍니다. TDD가 훌륭한 결과를 보장해주지는 않습니다. 왜냐하면 경험 없이는 좋은 설계를 할 수 없기 때문이죠. 대개 경험이 적은 사람들이 TDD를 하는 경우에는 리팩토링을 충분히 하지 않으며, 적당히 최적화된 설계를 하게 마련입니다. 여러분은 경험이 없는 개발자의 산출물과 경험이 있는 개발자의 산출물은 비교할 수 없습니다. 반드시 경험이 없는 개발자가 TDD 없이 작업한 결과물과 비교 해야만 합니다. 비록 측정할 수는 없지만, 이로울 것으로 보이며, 나중에 리팩토링을 통해서 개선하는 것 보다 쉽게 자가 테스트 코드를 만듭니다. 해서, TDD는 여러분에게 좋은 시작점을 제공합니다.
David : TDD로부터 얻은 가치에 대해 말씀 드리겠습니다. TDD를 시작할 때, TDD는 훌륭한 학습도구였습니다. (하지만 이번 논의는 충분히 나아가고 있지 않는 듯 하군요.) 저는 사람들이 신규 인력들에게 그대로 따르지 않을지라도, 간단하고도, 직관적이고, 겉만 번지르르한 조언을 달라고 말할 때마다 회의적이었습니다. 이는 제가 가르치는 것에 대한 확신이 부족하다는 것을 보여줍니다.
Martin : 저는 그런 독단적인 내용에 대해서는 동의하지 않습니다. 저는 제가 설명하고 있는 것에 반하는 논쟁거리를 찾지 못할 때 의심을 갖게 됩니다. 여하튼, 우리는 신규 인력에게 소개 세션을 반복하고 있습니다. 어떤 사람들은 기초를 반복하는 것일 싫어하거든요.
David : 바로 이러한 것들 때문에 우리가 지금 대화를 나누고 있다고 생각합니다. 사람들은 그들의 의견을 기초에 더했다고 말하곤 합니다만, 10년 뒤에는 시작지점 보다 한참이나 내려오게 될 것이며, 좋은 장소에는 있지 못하게 됩니다. 여러분은 리셋 버튼을 누를 필요가 있으며, 대충 무마 하는 것처럼 보이지만, 효율적입니다. 제가 TDD가 죽었다고 말할 때, 저는 현재의 변화에 대해 언급하였습니다 - 우리는 첫 번째 원칙으로 돌아가야만 합니다.
Kent : 제가 David의 원래의 키노트에 대한 본능적인 반응을 보인 것이 바로 그 부분입니다. 프로그래머들은 빈번하게 같은 작업을 반복하고, 코드를 지나치게 복잡하게 만들며, 제대로 동작하지 않는 시스템과 씨름을 할 것입니다. 저는 첫 번째 원칙으로 돌아가자는 것에 동의하지만, 지난 10년간 프로그램에 관한 사람들의 기대감의 발전을 잃고 싶지는 않습니다. 여러분은 반드시 확신을 느낄 수 있어야 하며, 전진하고 있다고 주장 할 수 있어야 하고, 생산적이고 기술적으로 협업 할 수 있어야 합니다. 저는 경력이 시작할 무렵에는 무척 부족하였습니다만, 이제서야 모든 일을 스스로 하고 있다고 느끼고 있습니다.
David : TDD, XP 그리고 Ruby는 동시에 우리에게 다가왔습니다. 사람들은 프로그램은 즐거워야만 한다는 말에 비웃었지만, 저는 Rails를 개발하면서 그 말을 계속하고 싶었어요. 제 생각에는 Ruby 세상에서는 그 행복이 찾아온 듯 하군요 - 그 말이 이겼습니다 - 바로 애자일을 가졌기 때문이죠.
Martin : 저는 애자일이 이겼다는 것에는 동의할 수 없습니다 - 애자일이라는 라벨이 이긴거죠. 그러나 많은 사람들이 애자일을 한다고 말하지만, 실제로 하고 있지는 않아요. 저는 이런 전형적인 현상을 나타내는 프로세스를 의미적인 유포(semantic diffusion)라고 말합니다. 큰 승리는 오늘날 우리가 애자일을 고객과 공개적으로 할 수 있게 된 점이죠.
David : 이러한 재시도 문제점은 다른 것들도 있어요 - 10년 뒤에 여러분은 싫은 것이 많아 질겁니다. 2 가지 맛으로만 시작하였던 Pinkberry를 예로 들어볼까요? 지금은 다른 아이스크림들과 마찬가지로 복잡한 범위의 맛들을 가지고 있죠 - "대부분의 사람들은 좋은 아이디어를 혼자 내버려두지 않으려고 하죠"
Kent : 저는 David가 경험한 TDD를 여태 본적이 없어요. 저는 언제나 첫 번째 원칙으로부터 TDD를 적용해왔으니까요. 하지만, TDD에 붙어 있는 따개비들을 떼어내야 한다고 주의를 준 David에게 감사를 표합니다.
David : Rails에서 비슷한 이슈를 본 적이 있습니다. 저는 Rails를 기초적인 폼 안에서 사용해 왔는데, 제가 본 일부 Rails 코드는 충격적이었죠.
Kent : XP가 주목 받기 시작할 때의 최초 OOPSLA가 생각나는군요.
Jim Rumbauch : David는 앞으로 지난 10년 동안 XP*에 벌어진 일들을 깨닫지 못할 것입니다. (그는 옳았습니다.) TDD는 성공하였고, 다른 대안들은 날아오르지 못했죠. 기술이 내재하고 있는 어떤 것 때문에 혹은 기술을 잘 못 사용한 것 때문에 나쁜 현상이 벌어지고 있다고 말하는 것은 언제나 어려운 일입니다. 우리가 할 수 있는 건, 기초적인 것과 좋은 교훈을 꾸준히 반복하는 것뿐이죠.
*역자주> XP : eXtreme Programming, SW 개발 방법론 중 애자일 실천 방법 중 하나
David : 동의 합니다. 당신은 영웅으로 죽거나 악당이 될 수도 있겠죠. Ruby는 프로그래밍에 관하여 좋은 아이디어의 재시도였습니다. 함수형 프로그래밍은 또 다른 재시도이죠. 이러한 재시도들은 건강합니다. 저는 Rails와 TDD가 오랫동안 함께 해온 것에 감명 받았습니다. 저는 Rails 이전에는 PHP로 작업을 했어요. 여러분은 잘 만하면 PHP로 좋은 코드를 작성할 수 있으며, 다른 프로그래밍 언어들로도 힘을 북돋아주는 좋은 사례들을 만들 수 있다고 느낍니다. 저는 MVC 기반 웹 애플리케이션에 TDD를 잘 사용하는 것은 깨끗한 PHP 코드를 작성하는 것 보다 어렵다고 생각합니다.
Kent : 전 제가 언제든지 TDD를 사용할 수 있다고 믿기 때문에, 그렇지 않은 경우를 찾지 못하겠군요. 저는 언제든지 다른 길로도 TDD로의 탐험을 하길 원합니다. 저는 제 경험과 함께 꾸준히 탐험할 것입니다. 지나치게 많이도 해보고, 충분하지 않게도 해보고, goldilocks zone도 찾아보며, 근본적인 원인을 이해할 것입니다. 저는 명확하게 David의 의견에 반박합니다. TDD는 죽지 않았습니다. 하지만 David가 TDD에 불을 질렀고, 마치 불사조처럼 튀어 나오게 된 점에 대하여 기쁘게 생각합니다.
David : 제가 이 논의를 시작하게 된 이유는 사람들이 TDD가 효과적으로 사용되지 않는 케이스에 대해 이야기 하려고 하지 않았기 때문입니다. 그들은 기분이 좋지도 않았거나 확신이 없었음에도 불구하고 반드시 TDD를 사용해야만 한다고 말하곤 했죠. 저는 타당한 반응에 대한 영역을 열기를 원했고, 이로 인해 우리는 TDD가 적절한 지 아니면 적절하지 않은 지에 대해 논의 할 수 있었습니다. 인터넷의 많은 사람들이 TDD가 얼마나 좋은지 말하고 있지만, TDD가 그들에게 잘 동작하고 있지 않다고 말하는 것을 두려워하고 있었습니다. 저에게 자가-테스팅 코드는 우리가 TDD에 대해 미심쩍어 할 때에도 잃고 싶지 않는 존재입니다.
Martin : (처음 시작하기 전부터 기대 했듯이) 우리는 많은 부분에 동의하였습니다. 우리 모두는 자가-테스팅 코드에 많은 가치를 얻고 있으며, 우리 모두 TDD가 어떤 곳에서는 가치가 있지만, 얼마나 많은 곳에서 가치가 있는지에 대해서는 (비록 말하기 어렵지만) 일부 동의하지 못하였죠. 만약, 여러분이 소프트웨어 개발을 하고 있다면, 이 점에 대해 반드시 깊게 생각해야만 한다는 것 그리고 당신과 당신의 팀을 위하여 잘 맞는 사례를 찾아내야 만 한다는 것, 그리고 여러분은 장님처럼 아무 기술이나 가져다 쓰면 안 된다는 것에 의견이 좁혀졌다고 봅니다. 여러분은 TDD를 시도할 필요가 있으며, 사용해야 하며, 남용도 해보고, 여러분과 여러분의 팀에 잘 동작하는 것이 무엇인지 찾을 필요가 있습니다. 우리는 공식으로 뒤덮인 과학 안에 있지 않습니다. 그렇기에 우리 스스로의 경험 기반으로 함께 일을 해야만 합니다.