레이블이 TDD인 게시물을 표시합니다. 모든 게시물 표시
레이블이 TDD인 게시물을 표시합니다. 모든 게시물 표시

2015년 1월 25일 일요일

어떻게 하면 사람들이 즐겁게 테스트를 작성하도록 할 수 있을까?

프로젝트에서 프로덕트로


 제임스 루이스와 마틴 파울러는 마이크로서비스에 대한 논문에서 마이크로서비스의 특징의 하나로 프로젝트에서 프로덕트로의 패러다임 전환을 꼽고 있다.

 하지만 이는 마이크로서비스에 대한 것 만은 아니다. 소프트웨어의 품질과 기능 그 모든면에서 프로젝트에서 프로더트로의 관점 전환은 대단히 중요한 요소이다. 오늘 소개할 InfoQ의 기사는 바로 그러한 관점의 전환이 소프트웨어 개발과 테스팅을 어떻게 바꿔 놓을 수 있는지를 보여준다.

 자동화 테스트는 메트릭스의 모피어스가 건네주는 알약과도 같아서 일단 처음 어느 정도 고통스러운 시기를 거치게 되지만 한번 제대로 동작하기 시작하면 자동화 테스트가 없는 개발로는 두 번 다시 돌아가지 못한다. 하지만 그 첫 걸음을 어떻게 하면 고통 없이, 또는 적은 고통으로 성공시킬 수 있을까?

 자신의 개발 조직에 자동화 테스트를 도입하려고 하고 있거나 이미 도입하였지만 제대로 정착 시키는 데에 어려움을 겪고 있다면 이 기사가 큰 도움이 되리라 생각한다.

www.workyouenjoy.com


어떻게 하면 사람들이 즐겁게 테스트를 작성하도록 할 수 있을까?


원문 링크 : Leading a Culture of Effective Testing


 저는 제가 개발에서 운영까지 책임을 맞았던 최초의 시스템을 지금도 잘 기억하고 있습니다. 다행히도 설계에서 지원까지 모두 맡았습니다. 몇 년 후, 그 시스템 중 하나의 하위 시스템이 자주 사용되게 되었습니다. 지속적인 기능 추가 요청이 오기 시작했고 복잡성은 증가했습니다. 변경을 할 때마다 나는 주의 깊게 기존의 기능을 확인 했습니다 만 수작업으로 하는 검사는 시간이 걸리고 기능 추가에 따른 복잡성의 증가는 폭발적으로 늘어났습니다.

 다른 사람들과 마찬가지로 나는 자동 테스트에 대해 들어 본 적이 있었지만, 그 방법을 배울 시간이 없었습니다. 그러다가 시간적 여유가 생겼을 때, 나는 몇 가지 책을 읽고 그 방법을 배웠습니다. 그 방법을 현실의 일에 적용 한 결과, 성장함에 따라 변경이 어려워 졌던 서브 시스템의 문제를 해결하기 위해 자동화 된 테스트는 완전한 방법이라고 느꼈습니다. 어느 날 오후, 나는 자동차 드라이브 나가고 있었습니다. 시간에 여유가 생겼던 겁니다. 인터넷에 연결되지는 않았지만 테스트를 작성하는 데 필요한 모든 도구를 가지고 있었습니다. 며칠 후 수동으로 실시하고 있던 검증의 세세한 부분 대다수를 자동화했습니다. 시간 절약 효과는 엄청난 것 이었습니다. 몇 시간 이나 필요했던 테스트가 불과 몇 초 만에 끝나버렸습니다.

 그러나 시간 절약은 두 번째 효과였습니다. 내 머릿속의 모든 시나리오가 크게 변화했습니다. 만든 것에 대한 신뢰의 감각이 되살아 난 것입니다. 아직 복잡성이 증가하지 않는 새로운 시스템에 대한 신뢰와 비슷합니다. 새 릴리스를 할 때 마다 불안감이 머리속을 떠나지 않았습니다. 여러 번 확인 했음에도 불구하고 불안은 사라지지 않았습니다. 응용 프로그램의 릴리스에 따른 지원은 만든 사람이 책임을 져야 했기 때문에 본능적으로 릴리스를 꺼리게 되었습니다. 이러한 상황에서 자동 테스트의 도입은 불안감을 안심으로 바꿔주었습니다.

 테스트에 누락이 있으면, 간단하게 테스트를 추가하고 다시 누락 되지 않도록 했습니다. 자신감이 생기자 위험을 감수하고 새로운 기능을 추가 할 수 있게 되었습니다. 또한 더 이상 문제를 무서워하지 않고 가치를 제공하는 데 주력 할 수 있었습니다.

 수동 테스트의 경우 테스트 시나리오는 수동으로 주의 깊게 설계하고 수동으로 실행하며 수동으로 확인 해야 합니다. 게다가 머리 속에 남아 있는 시간은 길지 않아 쉽게 잊혀집니다.

 자동 테스트의 경우, 시나리오, 실행, 검증은 모두 프로그램에 의해 문서화 되고 자동화됩니다. 유일한 수동 절차는 실행 버튼의 클릭 뿐입니다. 기억에 의존 할 필요도 없으며, 유통 기한이 지난 문서를 의지하여 시나리오를 쫓아 수동으로 수행 할 필요가 없습니다.

 대부분의 개발자가 테스트 자동화의 가치를 인정하면서도 그 혜택을 향유 하는 데 에는 실패했습니다만, 나는 다행히도 장점을 누리기 위한 올바른 방법을 찾을 수 있었습니다.

책임


 만약 제가 테스트에 대해 책임을 지지 않았다면, 테스트를 자동화하는 시간은 없었을 것입니다. 이것은 매우 간단한 것입니다. 자신이 개발을 지원하는 시스템의 사후 지원을 담당하는 것으로, 나는 소프트웨어가 제대로 작동하는지 보장하는 데 큰 관심을 갖게 되었습니다.  오전 5시 전화 받고 일어나 시스템 장애를 해결하는 사태를 막기 위해 나는 문제점이 이월 되지 않도록 꾸준히 노력해 왔습니다.

 개발자야 말로 만든 것을 어떻게 확인 해야 할지 가장 잘 알고 있습니다. 어느 부분에 자신이 없거나 어디에 복잡성이 존재하는지 어디에 문제가 포함될 여지가 있는지 잘 알고 있지요. 개발자 이외에 이처럼 포괄적인 관점을 가지고 있는 사람은 없습니다. 개발자는 작업 자동화 전문가이며, 검증 작업 자동화의 적임자입니다.

 많은 개발자들이 개발 한 시스템의 사후 지원이 가능하며, 그 책임을 다른 사람에게 전달하고 싶어하지 않습니다. 뭔가를 만든 사람은 그것이 성공하는 것을 희망합니다. 우리가 할 수 있는 것은 개개인이 어떠한 것에 대하여 공헌하고 싶어 하는지 묻는 것입니다. 책임을 공유하고 개발자가 시스템의 사후 지원에 기여할 수 있도록 하는 것이 효율적인 테스트의 이점을 누리는 방법입니다.

제각각인 팀을 융합하다


 만약 조직이 소프트웨어 개발의 책임을 여러 팀에 분산 시키게 되면 테스트를 하는 것은 힘든 작업이 됩니다. 불행히도, 고객의 납품이 완료된 이후의 시점부터는 이러한 어려움이 일상화되어 버리게 됩니다.

 테스트가 다른 팀에 맡겨진 경우 대부분의 경우 수동 테스트입니다. 자동화되어있는 경우에도 유지 보수하기 어려운 엔드 - 투 - 엔드 테스트입니다. 엔드 투 엔드 테스트는 운영 환경과 동일한 환경을 설정 해 줘야 합니다. 또한 개별 부분을 잘라낼 수 없습니다. 또한 뭔가 잘못되면 많은 테스트에 영향을 주고, 의미있는 피드백을 실패로 부터 얻을 수 없게 됩니다. 응용 프로그램 업데이트를 비활성화 버리는 취성 엔드 투 엔드 테스트 코드를 정기적으로 업데이트한다면, 수동 테스트에 회귀하는 것은 자연스러운 것입니다.

 분리 된 테스터가 응용 프로그램의 낮은 수준을 테스트 하기 위한 능력과 지식을 가지고있는 것은 드문 경우입니다. 특히 효과적인 검증 될 필요가 있는 단위 테스트 수준의 것은 알 수가 없습니다. 단위 테스트는 시스템을 작은 단위로 분리하고 확인합니다. 이 수준에서는 코드와 애플리케이션에 대한 깊은 이해가 필요 합니다 만, 개발자 만이 이에 대한 지식을 가지고 있습니다. 만약 개발에서 분리 된 테스터가 이러한 단위 테스트에 대한 지식을 지니고 있다면, 그 테스터가 개발팀이 아닌 것은 이상한 일입니다.

 또한, 테스트의 책임이 전가되어 버리면 개발자에게 소프트웨어를 성공적으로 움직이는 것에 대한 책임이 없다 라고도 할 수 있습니다. 하지만 그러면 개발자에게 신뢰하지 않는다는 메시지를 보내 버리게됩니다. 이것은 최악의 마이크로 관리입니다. 우리는 확인 사항이 줄을 설 정도로 많은 새로운 기능을 개발하고 있습니다. 실제로 테스트를 하고 피드백을 하는 데 몇 일, 몇 주 가 소요될 것입니다. 작은 문제가 숨어 있던 것 만으로도 새로운 기능의 구현에 장애가 될 수 있습니다. 그리고 기능 구현이 지연하면 급격하게 진행이 악화되고 마는 것입니다.

 이렇게 개발과 테스트를 분리하는 것은 자연스러울 지도 모릅니다 만, 결과적으로는 테스터의 레이어가 두꺼워지고, 몇 번이나 확인을 하게 되어 버립니다. 나는 3 개 이상의 분리 된 테스트 단계를 가지고 조직을 알고 있습니다. 이 경우 전체 프로세스가 멈추었습니다. 하나의 경쟁 상대가 책임을 직접 개발자와 공유하는 방식의 장점을 발견 하게 되면, 상대적으로 다른 기업에 불리한 위치에 서고, 결국 경쟁에서 질지도 모릅니다.

 책임과 권한의 명확화는 효율적인 테스트를 하는 데 매우 중요합니다. 하나의 팀이 테스트 지원에 책임을 갖게 합니다. 책임 여러 팀에 분산 되어 있다면, 하나의 팀으로 통합 해야 합니다. 테스터가 개발자의 옆에서 일을 하게 하는 겁니다. 또는 각각의 멤버들이 테스터와 개발자 모두의 역할을 서로 확인하고 편견을 제거합니다. 개발자가 일부 단위 테스트를 작성하고 다른 테스트 팀에 전달하는 것이 아니라, 단위 테스트와 엔드 - 투 - 엔드 자동화 된 테스트를 할 것인지, 아니면 수동 테스트를 할 것 인지를 상황에 따라 전체적인 의견을 통해 결정 하도록 합니다.

 새로운 팀의 업무 초첨은 단일 기능 또는 관련된 몇 가지 기능에 한정 시키는 것이 좋습니다. 이렇게 하면, 전원이 함께 일하고 하나의 기능을 개발하고 테스트 할 수 있습니다. 서로 상관 없는 변경 요소를 한 팀에 처리 시킨 다던지, 대규모 변경의 대응을 개발 팀 테스트 팀, 지원팀 사이에서 몇 달에 걸쳐 이동하는 것이 아니라 하나의 팀으로 작은 릴리스에 필요한 모든 것을 수행 하고 1 에서 2 주 기간으로 작업합니다. 이 제한적인 포커싱에 의한 개발 방법은 실제로 생산성을 향상 시키고 있습니다.

 작은 변경을 실시하는 것으로, 고객의 의견을 신속하게 받을 수 있게 됩니다. 변화가 작기 때문에 테스트 환경이나 스테이징 환경도 쉽게 준비 할 수 있고, 외부 고객의 리뷰에 더욱 포커싱 할 수 있게 됩니다. 고객이 확인할 내용에 대해서도 모호함이 줄어듭니다. 피드백이 오는 것도 빠르게 되어, 피드백에 대한 대응도 늦지 않게 됩니다. 큰 덩어리보다 작은 변화가 더 테스트하기 쉽기 때문입니다. 빠르게 피드백을 받고 빠르게 변경하고 출시하여 다음의 작은 기능 세트로 이동합니다.


자동 테스트의 가치를 보여주다


 팀 개개인이 개발, 테스트 및 시스템 지원의 책임을 가지게 되면 두 가지 선택이 있습니다. 하나는 팀이 수동으로 테스트가 효율적이고 않는다는 것을 깨달을 때 까지 기다리는 것. 다른 하나는 도박을 피하고 팀을 교육하는 방법 입니다. 적당한 지침 없이 자동 테스트를 실시하는 데 몇 년이 걸립니다. 개개인이 일상적인 업무량에 치이고 있는 경우에는 특히 그렇습니다. 자동 테스트를 도입한다고 해도 학습하는 데 몇 년이 걸립니다. 그러나 전문가의 도움을 받아 테스트 자동화의 가치를 알리는 것으로,이 기간을 단축 할 수 있습니다.

 자동 테스트에 완전히 매료되어 충분한 성과를 올린 후, 나는 다른 사람들도 동참 시키고 싶다고 생각 하게 되었습니다. 먼저 데모를 실시하여 자동화 된 테스트 도구의 활용 방법을 설명했습니다. 하지만 이 방식은 실패 였다고 생각합니다. 직접 실제 프로젝트에서 자동 테스트를 실시 할 수 있도록 지원하는 것이 아니라 시험 방법을 가르쳐 버린 것입니다. 가르치는 것 만으로는 부족합니다. 테스트의 가치를 증명하는 유일한 방법은 팀이 실제로 책임 지고 있는 일에 대해 테스트를 통해 자신감을 키우는 것을 도와주는 방법 뿐 입니다.

 가장 효율적인 것은 자동화 된 테스트 기법을 실천할 수 있는 기회를 만들고, 복잡하고 오류 나기 쉬운 응용 프로그램에 적용해 보는 것입니다. 개발자는 모두 까다롭고 다루기 귀찮은 시스템을 최소한 하나는 가지고 있습니다. 경험을 통해 불안감을 자신감으로 바꾸는 체험만이 자동화 테스트가 개발의 일부로서 받아지도록 하는 유일한 방법입니다.

개인 개발자가 다음과 같은 것을 경험하면 도입은 더 수월하게 진행 되겠지요.


  • 복잡성을 자동으로 테스트하는 것에 대한 신뢰.
  • 테스트 주도 개발의 경우 코드를 작성하기 전에 테스트를 작성하여 소프트웨어 개발을 진행해 나가는 것.
  • 의미 없는 테스트에 대해서 테스트를 자동화하는 것은 역효과. 이 트레이드 오프를 깨닫기 위해 몇 년을 낭비한다. 많은 자동화 된 테스트를 포기하게 되는 큰 원인.
  • 도구가 자동 테스트의 부하를 획기적으로 낮출 것.
  • 테스트는 소프트웨어의 변경과 기능 추가가 쉬워 기존 기능도 심플하게된다는 것.
  • 기존 문제의 근본 원인 분석 수정에 테스트가 도움이된다는 것.
  • 외부의 실시간 시스템과의 통합 등 수동 테스트가 불가능한 영역에서 자동 테스트가 효과를 발휘한다는 것.

개발자 툴 킷 중에서도 자동 테스트에 큰 가치가 있음을 증명하는 것은 간단합니다. 개발자가 자동​​ 테스트가 일을 개선해주는 것을 한번 경험하면 그 이후로는 단번에 가치에 대해 깨닫게 됩니다.

강제로 요구 하지 않기


 데모를 실시하고 자동화 테스트의 전파에 실패한 후, 나는 적어도 팀이 나를 따라 올 수 있는 상태를 만들고 싶다고 생각했습니다. 여기서 저는 또 다른 실패를 저지릅니다. 그것은 응용 프로그램의 일부에 대한 테스트를 쓰는 것을 의무화 한 것입니다. 이것이 실패한 것은 다음의 두 가지 이유에서 입니다.


  •  제 자신이 너무 많은 책임을 지고 말아 버렸습니다. 뭔가 좋지 않은 일이 일어 났을 때, 늦게까지 남아있는 역할 이었는데, 그에 따라 많은 테스트가 내 부담이 되었습니다. 나는 잘 작동하지 않을 것 같은 시스템의 일부에 대한 테스트를 선택했습니다. 하지만 테스트 케이스를 전달 하는 과정에서 본래의 의미는 사라져 버렸습니다.
  •  의미가 희석 되어 버렸으므로, 가치도 느껴지지 않습니다. 그리고 성급하게 테스트 케이스를 만들었습니다. 그 결과, 테스트 케이스의 질이 희생되었습니다. 이해하기 어렵고, 대충 적당한 , 때로는 부정확 한 사례가 되어 버렸습니다. 룰을 강제 하여 많은 테스트가 만들어 졌지만, 그 테스트가 쓸모 없다는 사실을 깨달았습니다. 목적을 잃어버린 테스트 작성은 벌칙 게임 같은 것입니다. 쓸모없는 테스트는 프로젝트에 유해한 요소가 되어 유지 보수 해야 할 코드의 양만 늘려버립니다. 또한 사용할 수 없는 시험은 장기적으로는 혼란의 씨앗입니다. 시간이 흐르면 의미 없는 테스트가 본래 시스템이 가져야 할 모습을 묘사하고 있는 것으로 둔갑하게 되기 때문입니다.

 책임을 공유하고 테스트 케이스의 장점을 근본부터 이해하게 된다면 그 이후로 프로그래머는 가치가 있는 테스트를 작성하기 시작합니다. 교훈은 매우 간단합니다. 즉, 강제하는 것은 피하라.

그 밖에도 몇 가지 피해야 할 사항들이 있습니다.


  • 코드 커버리지 수준을 강제한다.
    • 테스트 코드 커버리지는 테스트 케이스가 커버 하는 코드의 양을 측정합니다. 범위가 80 %라면 20 %의 코드는 테스트를 실행하여도 호출되지 않습니다.
    • 코드 커버리지는 테스트하지 않은 영역을 손쉽게 찾을 수 있는 긍정적인 면이 있기도 합니다. 그러나 테스트의 품질을 보장​​하는 것은 아닙니다. 테스트 케이스의 효과는 수치로 측정 할 수 있는 게 아닙니다. 또한 응용 프로그램은 테스트 할 가치가없는 영역도 있습니다. 따라서 100 %의 커버리지를 제공하도록 지시를하는 것은 현명한 생각이 아닙니다.
    • 코드 커버리지 수준을 강제하는 것은 쓸데없는 테스트를 많이 낳아 버립니다.
  • 코드를 작성하기 전에 테스트를 작성하도록 지시한다. 즉 테스트 주도 개발 (TDD).
    • TDD는 매우 중요한 기술입니다. 그러나 강제하는 방식으로는 진행하지 말아야 합니다. 응용 프로그램에는 TDD가 유효하지 않은 부분이 존재 하게 마련입니다. TDD의 가치를 나타내는 것은 좋은 것입니다. 그러나 개개인이 자신의 판단에 따라 실천 해야 합니다.
  • 테스트 수를 강제한다.
    • 이것은 코드의 라인 수를 지시하는 것과 같습니다. 의미가 없습니다.
    • 시스템에 불필요한 테스트가 있다면, 과감히 제거해 나갑시다. 테스트 코드는 유지 보수 해야 하는 코드의 양을 늘립니다.
 이러한 강제에 의해 개발자는 난처한 상황에 빠지고, 쓸데없는 테스트가 태어나 시스템의 유지 보수 용이성을 저하 시킵니다.



장애물을 제거


 개발자가 한 번 자동 테스트의 가치를 실감 한 후에는 실천에 들어가는데 걸림돌이 되는 장애물을 제거하는 것이 중요합니다. 장애를 제거하여 수동 테스트의 단점을 제거 할 수 있습니다. 테스트를 자동화하는 것을 어렵게 하고 있는 원인은 어떤 것이 든, 자동 테스트 구축을 실시하지 않는 이유 중 하나에 지나지 않습니다.

장벽을 제거하기위한 도구는 많이 있습니다.


  • 테스트 러너
    • 테스트 러너를 사용하면 신속하게 테스트 할 수 있습니다. 개발자가 사용하는 개발 환경과 통합하면 좋을 것입니다. 개발자가 TDD를 실천하고 있다면, 코드를 작성하는 만큼 테스트를 쉽게 하고 싶어할 것 입니다.
  • 코드 커버리지 측정
    • 코드 검사는 개발자가 응용 프로그램을 얼마나 테스트하고 있는지 알려줍니다. 한층 더 테스트를 추진하기에 훌륭한 도구입니다.
  • 지속적인 통합 (CI) 서버
    • 개개인이 테스트 케이스를 실행하는 이외에, CI 서버를 사용하여 변경이 발생할 때마다 자동으로 테스트를 실시합니다.
    • 테스트 전체를 실시 하는 것을 잊어서는 안됩니다. 안전망을 구축하는 것이 테스트의 가치를 높이는 것입니다. 안전망이 없어서 테스트가 무시 된 환경을 여러 번 본 적이 있습니다. 테스트가 작동 하고 있는지 않는지 조차 인식하지 못하는 경우도 있습니다.
    • 테스트가 실패하면 즉시 알려주기 때문에 문제를 빠른 시간 안에 바로 잡을 수 있습니다.
    • 개발자가 CI 서버를 신뢰하여 만든 테스트에 더 큰 가치를 인정하게 된다면 그 가치를 만끽 하기 위해 테스트를 빨리 만들고 싶어지게 됩니다.

 이러한 도구의 구입 비용을 가지고 고민하는 기업들을 여럿 보아왔습니다. 아이러니하게도 많은 도구의 비용은 개발자의 몇 시간 분 시급보다 낮을 것입니다. 효율적인 테스트를 실현하는 중요한 역할을 하는 도구의 이점에 대해 논하는 것은 시간 낭비입니다.

 지금 바로 실천을 통해 도구를 사용하여 오류를 제거합시다. 시작이 늦으면 늦을수록 손에 들어오는 가치도 작아 져 버립니다.


여유


 기법을 배우고 실천하는 데 필요한 여유도 테스트에 대한 장애 중 하나 입니다. 개발자가 여가 시간에 테스트를 테마로하고 배워주는 기대해야할까요? 아니면 일 동안 시간을​​ 확보하고, 이러한 학습을​​ 지원하는 편이 좋은 것일까 요.

 나는 오랫동안 다양한 테스트 기법의 학습과 적용에 종사하여 "자동 테스트 도구"어떤 때 유용 어떤 때 쓸모 있는지 본능적으로 알게 되었습니다.

개인에게 여유를 주고, 자동 테스트 기술의 연마를 지원합시다.


  • 고 부하 일정을 피합니다. 바쁜 와중에 학습을 동시에 진행 하기는 쉽지 않기 때문입니다.
  • 불필요한 작업은 중단합니다. 예를 들어, 수동으로 실시하는 테스트 케이스를 문서화하는 것입니다. 이렇게 하면 자동화 하는 인센티브도 생깁니다.
  • 자동 테스트를 낭비라고 느끼는 고객 및 이해 관계자도 있을지도 모릅니다. 미신은 추방합시다. 이런 이야기에 의욕을 잃어서는 안됩니다.
  • 무엇이 성공하고 무엇이 실패 했는 지를 자주 되돌아 봅시다. 모두가 배운 것을 공유하고 성과를 서로 치하 할 수 있도록 합시다.



성과에 주목하자


 내가 참가한 가운데 가장 효과적인 테스트가 행해진 프로젝트는 모두가 소프트웨어의 성과에 주목하고 있던 프로젝트였습니다. 어떤 보고서를 작성해야 할지 지시를 받는 것이 아니라 내가 원하는 비즈니스 성과를 이해하고 어떠한 보고서가 필요한 지를 결정하는 데 도움이 될 수 있었습니다.

 시스템의 어느 부분이 가장 비즈니스 성공에 기여하는지 이해하고 있었기 때문에 그 부분에 주력했습니다. 비즈니스의 바람직한 성과를 바탕으로 테스트 우선 순위를 정하고있었습니다. 또한, 성과의 관점에서 테스트를 설계하고 있었으므로, 테스트의 기대 값에 대해 고객이나 사용자에게 직접 설명 할 수있게되어있었습니다.

 이것은 테스트에서 최대한의 가치를 끌어낸 예입니다. 이것을 목표로 해야만 합니다. 비즈니스에 가치를 추가하지 않는 코드와 테스트를 억지로 만들어야 하는 것 처럼 우울한 것도 없습니다.


신뢰


 복통을 일으켰다고 합시다. 병원에 도착했을 때, 당신은 접수 계원에게 증상을 설명합니다. 접수 계원은 맹장 상단의 복부를 절개하는 의사에게 진찰을 요구합니다. 그리고 맹장을 절제하는 것을 전문으로 하는 의사도 부릅니다. 또한 절개 한 복부를 봉합 의사도 부릅니다. 당신은 회복실로 옮겨진 이후 의사로 부터 연락이 끊깁니다. 아직 복통이 있습니다. 다시 진찰 해 보니 하면 통증은 담낭이 원인이었습니다. 맹장은 문제 없었습니다.

 다행히도 우리는 이러한 세계와는 무관합니다. 의사의 업무는 내장을 제거하는 것이 아닙니다. 무엇보다 이렇게 하는 전문 능력은 가지고 있지만. 그들은 진찰 부탁 받아 주의 깊게 분석 한 후 해결책을 처방합니다. 수술의 경우 절개를 하고 배운 것을 바탕으로 진단을 확인합니다. 어떤 경우에도 올바른 길을 확보합니다. 수술 후에도 수술이 완벽하다는 것을 알 때까지 환자를 돌봅니다. 그리하여 안전하다는 확신이 들면 회복실로 보내집니다. 회복시에도 상황을 확인하고 회복을 지원하기 위한 조언을 준비합니다. 의사가 아닌 사람도 환자의 용태를 확인하고 있지만 궁극적으로는 의사가 환자의 회복을 담당합니다.

 만약 의사에게 자신의 생명을 맡길 수 있다면, 마찬가지로 자신이 사용하는 소프트웨어 개발자를 신뢰 하는 것도 가능하지 않을까요?



저자에 관하여


 Wes McClure 씨는 기술과 소프트웨어로 기업이 눈부신 성과를 달성 하는 것에 열정을 가지고 지원하고 있습니다. 소프트웨어 개발의 폭 넓은 경험을 바탕으로 비즈니스 목표에 부합하는 소프트웨어를 개발하는 방법의 개선을 실시하고 있습니다.  Full City Tech를 시작해 전문성을 활용하여 고품질의 소프트웨어를 신속하게 제공하고자하는 기업을 지원하고 있습니다.


2014년 8월 3일 일요일

TDD는 벌거벗은 임금님의 투명옷인가? (3) - TDD는 UT가 아니다.

TDD는 벌거벗은 임금님의 투명옷인가?




 각종 커뮤니티에서 난리가 나고 업계의 거두가 모여서 현피맞장까지 뜬 TDD를 둘러싼 일련의 소동에 대한 핵심은 다음의 한문장으로 요약될 수 있을것이다.
테스트를 먼저 작성하고 코드를 적는것이 정말로 개발에 그만큼의 가치를 가져다 주는가? 
 그리고 당연하게도 이 물음이 TDD. 즉 테스트 퍼스트 개발을 둘러싼 논쟁의 핵심이 되었어야만 했다.

 TDD의 창시자는 누구이던가? 오늘날의 개발자에게 있어서 십계명이나 다름없는 그 유명한 애자일 선언에 참여한 맴버중에서도 맨 첫머리에 이름을 올린 Kent Beck선생이 아니시던가! 하지만 이러한 '이름의 권위' 앞에서 TDD는 자동화 테스트와 동일시 되어 버려 그 가치를 올바로 평가받을 기회를 잃어버렸던게 아닐까?



 하지만 TDD에만 포커싱을 했으면 좋았을 DHH의 지적질에 애먼 유닛 테스트(이하 UT)가 포함되는 순간, 토론의 목적지는 저 멀리 안드로메다로 재 설정 되어 버리고 만다. Mock오브젝트에만 의존하는 생각없는mindless UT에 대한 반감은 TDD옹호론자라고 해도 공감하는 부분이지만, 엄연히 TDD와 UT에 대한 논쟁은 구분되어 이루어져야 만했었다.

 결론적으로 Martin Flower가 주최한 6회에 걸친 토론중에서 순수하게 TDD자체의 유용성에 대한 토론은 얼마 되지 않았으며, UT에 대한 유용성은 지금와서 이야기 하는것 자체가 무의미할 정도로 업계 전반에서 이미 상식으로 받아들여지고 있는 상황 이므로 아무런 의미가 없었다.

 나름 업계의 존경을 받는 머리 좋은 양반들이 그 귀중한 시간을 내어서 공개적으로 진행한 이벤트 치고는 참으로 어처구니 없는 전개가 아닌가? (그런데 토론을 자세히 보면 능구렁이 같은 Kent Beck이 덩치에 어울리지 않는 애교를 섞어가며 TDD에 대한 논점을 교묘히 흐리는 장면을 자주 볼 수 있다.)

 다시 TDD의 이야기로 돌아와 보자. 
 UT와 뒤섞여 버린 진흙탕 싸움에서 TDD에 관련된 쟁점을만을 분리해 보면 다음의 세가지로 요약된다.
  1. TDD는 오버헤드가 너무 크다  TDD는 커버리지를 중시하지는 않는다고 하면서도 모든 코드에 대한 테스트코드의 작성을 의무화 함으로서 이에 위배되는 모습을 보인다. 결국 개발자는 쓸데 없는 UT작성에 많은 시간을 빼앗길 수 밖에 없다. 하지만, 어느정도 비용이 소요된다 하더라더 테스트 코드가 없는 코드 보다야 훨씬 나을수도 있지 않을까?
  2. TDD가 설계를 망친다  테스트를 먼저 작성해야만 본 코드를 작성하도록 강제하는 룰은 시간에 쫒기는 개발자에게 유닛 테스트를 작성하기 쉬운 설계를 은연중에 강요하게 된다. 이는 결국 유닛테스트를 작성하기 어려운 시스템 횡단적인 기능을 기피하게 만들고 시스템의 설계를 기형적인 모습으로 만들것이다.  
  3. TDD가 테스트를 망친다  1,2와 관련하여 결국 UT만이 너무 강조되는 상황에서는 mock에 의존한 하나마나한 형식적인 테스트로 흐르기 쉬우므로 우리는 이 점을 경계해야만 한다. 또한 UT만큼이나 시스템테스트, 시나리오 테스트도 자동화에 힘을 기울일 수 있어야 할 것이다. 
Tip 요즘 많은 프로젝트들에서 빠르게 실행되는 UT와 시간이 걸리는 DB를 사용하는 결합테스트, 또는 시스템 테스트를 분리해서 구성하고 있다. UT는 커밋시에 개발자 스스로 체크하도록 하고 시간이 걸리는 DB나 그 밖의 미들웨어를 사용하는 테스트는 UT와 함께 젠킨스 등의 CI툴을 이용해 코드 변경시에 실행되도록 해 놓으면 개발자의 시간을 절약하는데 많은 도움이 될 것이다. 아울러 특정 DB에 종속되지 않는 퍼시스턴스라면 UT에도 인메모리 DB를 사용해 테스트 속도를 고속화 할 수 있다.

 TDD가 유용한지 아닌지는 현재 작성하는 프로그램의 성격과 내용, 그리고 작업자의 숙련도에 따라 달라지겠지만 어느정도 오버헤드를 감수해야 함에는 틀림없는 사실이다.

 그리고 여기서 한가지 간과하지 말아야 할 사실은 TDD의 태생이다. TDD는 초기 에자일 프로세스중 하나인 eXtreme Programming과 함께 2000년대 초반에 등장하였는데, 당시엔 오늘과 같이 xUnit테스트가 일반적이지 않았고 대부분의 테스트가 수작업에 의존하던것이 당연하던 시절이다. 이러한 당시 상황속에 UT의 작성을 의무화 하기 위한 하나의 충격요법으로서 XP와 함께 탄생한 TDD를 오늘날에 와서까지 굳이 이를 따라야 할 필요가 있을까?

 필자는 UT가 실행코드와 함께 필수로 받아들여지고 있는 현 시점에서 TDD가 더이상 큰 역할을 하기 어렵다는 DHH의 주장에 동감한다. 이상적인 자동화 테스트 코드는 맹복적인 코드 커버리지보다는 프로그램이 어떻게 움직여야 할지를 기술하는 문서화의 한 형태여야만 하기 때문이다. 반대로 자동화 테스트가 프로그램의 동작을 충분히 설명해 주지 못하고 있다면 추가나 보완이 필요하다고 봐야 한다.

 TDD의 채택여부는 프로젝트의 내용이나 구성원의 취향에 따라 충분히 어느쪽도 선택 가능할 것이다. 하지만, 어떠한 경우라도 자동화 테스트가 없는 개발만큼은 피해야 한다. 이것이야 말로 현대 소프트웨어 개발에 있어서 의심할 여지가 없는 진리이다.

2014년 7월 21일 월요일

TDD는 벌거벗은 임금님의 투명옷인가? (2) - TDD의 사망에 대한 검증

TDD는 벌거벗은 임금님의 투명옷인가?



이번 포스팅에서는 지나번 소개한 Rails의 개발자 DHH의  "TDD는 죽었다. 테스트여 영원하라!"에 뒤이어 펼쳐진 TDD에 대한 일련의 논쟁을 다뤄보도록 하겠다.

 DHH는 이후 "테스트를 위한 설계의 폐해Test-induced design damage"과 "데이터베이스 테스트는 느리다라는 편견Slow database test fallacy"라는 포스팅을 추가로 발표한다. 시간도 많고 영어에 자신이 있다면 위의 글들을 한번 읽어 보는것도 좋겠지만 요점정리 중심의 참고서 교육에 길들여진 분들을 위해 InfoQ관련 기사('TDD 사망'에 대한 검증Examining the 'TDD is Dead' Controversy) 내용을 소개한다. (필자의 견해는 - 이후 각주 형태로 추가하였다.)

원문 :  Examining the 'TDD is Dead' - InfoQ

DHH의 주장 요점정리

  • 많은 개발자들이 TDD를 사용하지 않는 코드는 더티한 코드라고 생각하도록 몰아넣고 있다. - 사실상 DHH가 이 논쟁을 시작하도록 한 직접적인 원인이 아닌가 싶다. 누군가 DHH에게 "니 코드는 구려. 유닛 테스트가 없쟎아?" 이렇게 말한것이 아닐까?
  • 유닛테스트 주도의 설계는 좋은 생각이 아니다. - TDD 근본주의자들은 제대로 된 설계는 테스트하기가 쉽다고 말한다. 필자는 이것을 부정하진 않는다. 하지만 '테스트하기 좋은 설계' = '좋은 설계'가 성립하는것은 아니다.
  • TDD의 개념인 "테스트는 빨라야 한다"는 근시안적인 생각이다. - 아무래도 테스트의 속도는 개발자 환경에선 부담이 될 수밖에 없다. 다행이도 젠킨스와 같은 자동화CI 툴이 도입된 이후로는 이러한 부담이 많이 줄었다. 자동화 테스트를 돌릴 수 있는 환경만 만들어 놓는다면 개개인은 자신의 코드에 대한 풀테스트 결과는 CI서버 상에서 확인 가능하게 되며 개인레벨에서 코드 커밋 이전에 수행해야만 하는 테스트는 코드에 의해 새로 작성된 테스트 케이스의 결과 확인만으로 충분할 것이다.
  • TDD에 대한 믿음은 시스템 테스트를 완전히 잋어버리도록 만든다. - DHH의 이러한 생각은 시스템 테스트나 시나리오 테스트를 자동화 하도록 권장하는 BDD의 영향을 받은듯 싶다. 실제로 Ruby에서는 BDD툴인 RSpec이 큰 인기를 누리고 있다.
  • 유닛테스트에 포커싱을 하거나 유닛테스트만을 행하는것은 큰 규모의 시스템을 만드는데에 도움이 되지 않는다. - 큰 규모의 시스템을 만들기 위해서는 반드시 여러 레이어를 횡단하는 테스트의 도움이 필요하다.
  • 100% 커버리지는 웃기는 이야기다 - 100% 커버리지 달성에 목매는 개발현장을 심심찮게 본다.  이런 현장에는 십중팔구 생각하기 싫어 하는 PM이 존재한다. 100% 커버리지는 품질에 대한 그 어떤 보장도 되어주질 않는다.
  • 프로그래머는 소프트웨어가 과학이 되길 원한다. 하지만 소프트웨어는 과학이 아니다. 그것은 좀 더 문학 창작에 가깝다. - 얼마전에 해커와 화가를 읽으면서 공감했던 부분.
  • 좋은 소프트웨어는 엔지니어링과는 다르다. 
  • 그것은 마치 글쓰기와 같다.  명확하고 간결한 글이 난해한 글보다 낫다.
  • 명확함은 좋은것이다. 따라서 테스트 커버리지나 테스트 스피드가 아니라 명확함이야 말로 추구하는 목표중 하나가 되어야 한다. 
  • 좋은 개발자가 되는것은 좋은 작가가 되는것만큼 어렵다. - 아무리 그래도 좋은 작가가 되기 보다는 쉽지 않을까? 아무리 생각해 봐도 좋은 개발자의 수가 좋은 작가의 수보다는 많아 보인다.
  • 글쓰기와 마찬가지로 좋은 프로그래머가 되기위한 가장 명확한 방법은 많은 소프트웨어를 만들어 보고, 또 좋은 소프트웨어의 코드를 읽어보는것이다. - 100%공감한다. 

커뮤니티에서 이에대한 반응은 광범위하게 나타났으며(트위터의 관련 해시태그#tddisdead를 보라), 반응또한 "역시 그렇군"에서 "멍청한 소리다"까지 다양하게 나타났다.

응답의 대부분은 TDD를 좀 더 실용적으로 적용할 필요가 있음에 초첨을 맞추고 있다.

스스로를 소프트웨어 장인집단으로 부르는 8thlight의 대표 Martin은 자신의 블로그에서 "만약 당신이 TDD를 하지 않으면서 TDD 만큼 효과적인 다른 무언가를 하려고 한다면, 기분이 나빠지게 될 것이다."라고 말한다. 그의 이야기를 좀 더 들어보자.

왜 우리는 TDD를 하는가? 우리는 TDD를 한가지 가장 중요한 이유와 다른 몇가지 덜 중요한 이유때문에 실시한다. 덜 중요한 이유들은 다음과 같다.
  1. 디버깅에 쓰는 시간을 줄일 수 있다.
  2. 테스트 자체가 정확하고 꼼꼼하며 명확한 가장 저레벨의 시스템 사양이 된다.
  3. 테스트 우선 개발에 있어 각각의 테스트는  다른 테스트들과 디커플링 될 필요가 있다. 우리는 이러한 디커플링이 유익하다고 믿는다.
이러한 것들이 덜 중요한 TDD 도입의 필요성들이다. 그리고 이것들은 아직 논쟁의 여지가 있다. 그렇지만 가장 중요한 이유에 대해서는 논쟁의 여지가 없을것이다.
  • 만약 당신이 실뢰할 수 있는 자동화 테스트를 가지고 있다면,  그리고 그 테스트가 언제든지 실행될 수 있다면 , 당신은 테스트가 모두 통과되었다는것 하나만 가지고도 아무런 두려움 없이 빠르고 간편하게 코드를 개선해 나갈 수 있다.


Martin Fowler “Hey. Soap. You wanna know this week’s Lotto numbers?”
Martin Fowler "My war ends with you."

Martin Fowler는 DHH와 Kent Beck을 초대하여 둘 사이의 논쟁을 중계하였다. (Kent Beck은 DHH의 포스팅에 대해 즉각적으로 반응했었다.)

리즈시절의 Kent Beck 사진.
2014년 7월 시점의 Kent Beck 페북 프로필 사진.
외모와는 달리 구글 플러스의 이벤트로 진행된  토론에서의 모습은 애교가 넘치신다.

Martin Fowler는 이번 토론에 대해서 다음과 같이 요약했다.
1)우리는 TDD의 흐름에 대해 우리들의 경험을 이야기 했는데, 방법론으로서의 TDD와 자동화 코드는 자주 혼동되어졌다.
2)DHH는 hexagonal rails와 같은 테스트 주도 개발의 접근방식에 의한 테스트 코드를 의식한 설계가 과도한 간섭과 복잡성으로 인해 망가질 수 있다고 생각한다. Kent는 그것이 TDD에 기인한 문제라기 보다는 설계 자체의 품질 문제라고 생각한다.
3)우리는 프로그래밍을 하는동안 피드백을 얻을 수 있는 당양한 체널을 통해 논의를 진행하고, 품질보증의 피드백을 개발자들에게 제공한다.
4)우리는 테스팅과 TDD의 몇몇 단점들에 대해서 논의했다. 당신은 너무 많은 테스팅을 하고 있는가? 그리고 그러한 테스팅은 기능 코드가 가져다 주는 가치보다 팀에게 더 많은 가치를 제공하는가? - 테스트 코드와 실행코드 사이의 밸런스에 대해서 생각해 보자.

Gergely Brautigam은 "TDD는 죽었다. - 사실이 아님TDD is Dead - Not really"라는 제목의 포스트에서 다음과 같이 말하고 있다.

TDD는 죽지 않았다.  명백하게 아직도 많은 사람들의 지지를 받고 있는데 어떻게 죽었다고 할 수 있는가?  이것은 마치 디자인 패턴은 죽었는가? 또는 Functional Automation이 죽었는가? 또는 오레오 쿠키는 죽었는가? 와도 같은 질문이다.
그렇다. TDD는 죽지 않았다. 그리고 지금까지 죽은적도 없다. 그것은 아마도 새로운것으로 변화 하거나 보다 나은것으로 바뀔 수는 있을것이다. 하지만 절대 죽지는 않는다. 그러므로 이 이야기는 이제 그만두자.
그는 다양한 레벨에서의 데트팅의 중요성과 일반적으로 테스트가 제대로 이뤄지지 않는 많은 팀들에 대한 이야기를 이어갔다. 그는 테스트 코드를 작성하지 않는 일반적인 이유로서 품질에 대한 관심부족과 시간에 쫓기는 많은 개발자들을 예로 들었다.
그의 결론은 다음과 같다.

그것은 소프트웨어 테스팅에 대한 10년간의 관찰과 경험속에서 얻은 저의 결론입니다. 시작은  가벼운 틀 위에서 진행하고, 몇가지 선행 테스트들은 당신이 이것을 오래 지속하는데 도움을 줄 것입니다. 적어도 한두개의 납입테스트는 당신의 비즈니스 로직을 더 잘 이해하는데 도움을 줄 것입니다. 한두개의 유닛테스트 역시 당신이 당신의 로직을 이해하는데 도움이 될껍니다. 나는 빌어먹을 모든 테스트를 전부 다 하라고 말하는게 아닙니다. 내가 아는 한 당신은 그럴 필요가 없습니다. 하지만,  품질을 위해서 최소한 몇개는 작성해야 합니다.

Gil Zilberfeld는 애자일 선언문으로부터 다음과 같은 포인트를 찾아내었다.
우리는 소프트웨어를 개발하고, 또 다른 사람의 개발을 도와주면서 소프트웨어 개발의 더 나은 방법들을 찾아가고 있다. 우리는 아직 완벽한 방법을 알아내지는 못했다.  TDD는 다른것들과 마찬가지로 보다 나은 소프트웨어 개발을 위한 여정에서 찾아낸 아이템들중 하나일 뿐이다.

2014년 5월 14일 수요일

TDD는 벌거벗은 임금님의 투명옷인가? (1) - TDD는 죽었다. 테스트여 영원하라!

TDD는 벌거벗은 임금님의 투명옷인가?



지난주 금요일(2014년 5월 9일) 밤 10시.
스텍오버플로StackOverflow를 비롯해 많은 IT커뮤니티를 술렁거리게한 IT업계의 드림매치가 30분간 차분히 이루어졌다.



발단은 Ruby on Rails의 개발자로 유명한 David Heinemeier Hansson(이하 DHH)가 자신의 블로그에 'TDD는 죽었다. 테스트여 영원하라!TDD is dead. Long live testing.'라는 다소 자극적인 제목으로 블로그 포스트를 올린데서 시작되었다.

David Heinemeier Hansson. 덴마크 출신 프로그래머로 Ruby on Rails의 제작자로 알려져 있지만 르망 24에 출전하는등 프로 레이서 로서의 일면도 가지고 있다.(엄친아?) 사진의 포즈는 보통 중딩들이 새로 산 시계를 자랑하고 싶을때 하는 포즈이지만 신경쓰지 말도록 하자.
여기에 XP와 TDD의 창시자인 Kent Beck선생은 RIP TDD 라는 페이스북 포스팅을 통해 DHH의 의견에한 자신의 생각을 밝힌다.

여기에 쌈구경에 재미가 들린 Martin Fowker선생이 멍석을 깔아준다.
바로 구글 플러스를 통해 두사람의 토론을 온라인 생방송 이벤트로 만들어 버린 것이다.
Is TDD dead?

일단 내용이 만만치 않으므로 이번 포스팅은 세 단원으로 나눠서 작성할 예정이다.


  1. TDD는 죽었다. 테스트여 영원하라! - David Heinemeier Hansson의 블로그 번역
  2. TDD여 편히 잠들라 - Kent Beck의 페이스북 번역
  3. TDD는 죽었는가? - DHH, Kent Beck, Martin Fowler의 온라인 토론 이벤트 정리


아직 국내에는 이름이 생소한 DHH이지만 비교적 젊은 나이에도 불구하고 (79년생) 프레임워크에 있어서 Ruby on Rails가 지닌 지위와 영향력을 생각해 본다면 소프트웨어 업계에 있어서 결코 무시할 수 있는 인물이 아니다.

오늘은 첫번째로 DHH의 주장을 담은 블로그의 글을 번역하는것으로 TDD에 대한 논쟁을 시작해 보고자 한다.

TDD는 죽었다. 테스트여 영원하라!

원문: TDD is dead. Long live testing.

테스트 주도Test-first개발 근본주의는 금욕만을 강조한 성교육과 같이 자기혐오를 불러오는 비현실적이자 비효율적인 도덕 캠페인과 같다.

처음시작은 달랐다. 내가 처음 TDD를 접했을때, 그것은 마치 프로그래밍의 신세계가 내 눈앞에서 열리는것 같았다. 그것은 테스트가 없는 세계로부터 테스트를 당연히 여기는 세계로의 의식개혁과도 같은 것 이었다. TDD는 제대로 테스트된 코드가 주는 평온함에 눈을 뜨게 해 주었고, 코드 변경시에 안정감을 가져다 주었다.

테스트 우선 개발은 자전거의 보조바퀴와도 같은것으로, 테스트는 프로그램을 보다 싶도있게 통찰할 수 있게 해 주었으나 나는 곧 그만두었다.

시간이 흐르면서 테스트 우선이란 슬로건은 점점 더 큰고 격렬한 목소리를 내기 시작했다. 테스트우선 개발을 실행하지 않는것은 죄악시 되었고 나 자신도 그러한 근본주의 소용돌이에 휘말려 들었는데, 그것은 마치 종교적인 금욕주의 가르침을 따라가지 못하는 자신이 부끄러워지는 느낌이었다. 그리하여 나도 테스트 우선 개발을 시험해 보기로 했지만 몇주만에 결국 그만 두었다. 테스트 우선 개발이 내 설계를 망쳐놓기 시작했기 때문이다.

테스트 우선 개발은 마치 광신도의 신앙심에 대한 자부심과도 같이, 오직 교리에 적힌 한구절 한마디를 충실히 지키는 것 만이 천국에 이르는 유일한 길이고, 그대로 하지 않으면 지옥에 떨어진다고 하는 희열과 절망의 요요였다. 그리고 그것을 그만둔 나는 모두 함께 가는 버스에서 혼자만 내린 기분이었다.

아마도 처음에는 자동화된 회귀 테스트 따위는 없어도 된다라고 하는 업계의 관행을 부수기 위한 충격요법으로서 테스트 우선 개발이 필요 했을지도 모른다. 아마도 처음에는 글자 곧이곳대로 일상적으로 수행하는 프로그램 개발에 적용하는것을 의도하지는 않았을지도 모른다. 하지만 어찌되었든 시작을 한다고는 해도 금방 중단되기 일쑤였지만, 불경한자를 단죄하는 헤머와도 같이 TDD를 성실히 행하지 않는것은 프로 소프트웨어 개발자로서의 자격이 없다고 낙인 찍혀 버린다. 이것은 리트머스 테스트이다. (단순한 기준으로 흑백이 구분되어버린다는 뜻:역자주)

이제 충분하다. 그만 두겠다. 나 데이빗은 더이상 테스트 우선 개발을 하지 않는다. 나는 더이상 그것에 대해서 사과하지도 숨기지도 않겠다. 나는 TDD가 회귀 테스트에 눈 뜨게 해 준것에 감사한다. 하지만 더이상 TDD에 끼워 맞춰 프로그램을 설계하지는 않는다.

나는 여러분께 TDD적인 접근이 정말로 당신의 시스템의 완전성과 일관성에 어떠한 영향을 주고 있는가를 진지하게 다시 검토해 보기를 권한다. 만약 이것이 정말 좋은것은 아닐지도 모른다는 가능성을 심각하게 받아들이게 된다면, 당신은 메트릭스에 등장하는 붉은 알약을 먹는것이 될 수도 있다. 그리하여 직면하게된 현실 세계는 당신이 원하던 것이 아닐 수도 있다.

그럼 이제 어디를 향해야 하는 것 인가?

최초의 한걸음은 문제의 존재를 인정하는 것 이다. 여러분도 여기까지는 동의할 것으로 생각한다.  그 다음은 메소드에서 시작해 시스템 전체에 이르는 다양한 범위의 테스트에 대해 균형을 잡는것이다. 지금의 열광적인 TDD열풍은 유닛(메소드) 단위의 테스트에 초점이 맟춰져 있다. 왜냐하면 이름 그대로 유닛테스트의 범위는 유닛에 한정되어 버리기 때문이다. (원래부터 테스트 우선 개발의 근거가 이것이다.)
하지만 나는 이것이 올바르지 않다고 생각한다. 테스트 우선개발의 유닛테스트는 중간적인 오브젝트나 간접적이고 지나치게 복잡한 구조를 낳기 십상이다. 게다가 느려지는것을 피하려고 하다보니 데이터베이스나 I/O관련 테스트도 기피하게 된다. 브라우저를 이용한 시스템 전체의 테스트도 지양하게 되어 버린다. 그 결과, 진정 무서운 괴물과도 같은 프로그램 구조가 탄생하게 된다. 서비스오브젝트라던지 커맨드패턴이 형편없이 얽히고 설킨 정글과도 같은 아키텍쳐 말이다.

나는 전통적인 의미의 유닛테스트는 거의 하지 않는다. 모든 의존관계를 목(Mock)으로 하면, 수천건의 테스트가 수초만에 끝나는 유닛테스트 이지만, 레일즈Rails 어플리케이션의 테스트에 있어서 좋은 방법은 아니라는, 단지 그 이유 한가지이다. 나는 실제레코드를 직접 데이터베이스에 억세스하여 동작시키는 방식으로 테스트를 진행한다. 상위레이어에는 컨트롤러 테스트가 있지만, 나는 어느쪽인가 하면 상위레이어에 대한 시스템 테스트는 Capybara나 이와 비슷한 것을 사용하여 테스트하는 편이다.

나는 이것이 우리가 가야 할 방향이라 생각한다. 유닛테스트의 중요도를 내리고, 설계의 일부로서 테스트 우선 개발을 사용하지 않는것이다. 그리고, 보다 시간이 오래 걸리긴 하지만 시스템 테스트의 중요성을 부각시켜야 한다.(게다가, 클라우드의 등장으로 테스트조차도 클러스터링이 가능해 짐에 따라 더이상 시스템 테스트도 느리지만은 않다.)

Rails는 이러한 전환에 도움이 된다. 오늘, 우리는 풀 시스템 테스트 자동화를 장려하기 위해 아무것도 하지 않는다. 정답은 미리 준비되어있지 않다. 단지 실수를 고쳐나갈 뿐이다. 하지만, 여러분은 굳이 실수를 할 때까지 기다릴 필요가 없다. 오늘 당장 Capybara를 돌려보라. 그리고 내일이면 좋은 아이디어가 우리들 머리속에 가득할 것이다.

자, 우선은 심호흡을 하자. 우리가 지금 하려는 것은 신성한 암소를 도살하는 것 이다. 고통스럽고 피를 보는 과정이 수반될 것이다. TDD는 이미 성공적으로 많은 프로그래머들의 머리속에 자리잡고 있다. TDD는 그들이 하는 행위가 아닌 그들 자신이 되어버린 것 이다. 그러한 사람들을 원래대로 돌리기 위해서는 커뮤니티를 만들어 진지하게 임하지 않으면 안되고, 시간또한 오래 걸릴 것 이다.

여기서 우리가 저지를 수 있는 최악의 선택은 또다른 테스트 종교를 만드는 것이다. 이를테면 "시스템 테스트야 말로 진리이다!"와 같은 또다른 황금소의 우상을 만드는 모습이 눈앞에 선하다. 제발 그러지는 말았으면 한다.

그렇다. 나에게 있어서 테스트 주도 개발은 죽었다. 하지만 그 죽음을 축하하며 무덤앞에서 춤을 춘다던지 단점을 조롱하기 보다는, TDD가 소프트웨어 개발에 가져온 기여에 존경을 표하고자 한다. TDD는 우리들의 역사에 중요한 족적을 남겼다. 그리고 지금은 그 다음을 향해 가야할 시간이다.

테스트여 영원하라!