실무에 혹은 진행중인 프로젝트에 TDD 적용하고 계신분??

hbull의 이미지

갑자기 궁금해졌습니다.

제가 아직 겪어보지를 못해서요.
실제로 TDD를 적용하고 개발하는 곳이 있는지, 그리고 TDD 를 적용하여 개발할 경우 어떤 장단점이 있는지,
경험이 있으신분 계시면 답변 부탁드립니다.

그럼 좋은하루되세요

익명 사용자의 이미지

프로젝트 규모가 작을때는 대충대충해도 굴러가겠지만,
여러사람이 협업을 하게되는 개발시 혹은 프로젝트의 규모가 점점 커지는 경우에는 TDD는 필수일 것입니다.

TDD에 대한 전문적인 지식같은 것이 없더라도 누구나 한번쯤은 개발단계에서 TDD를 자신도 모르는 사이에 썼을겁니다.
예를들어 어떤 단위 동작이 제대로 돌아가는지를 확인하기위해 간단한 테스트프로그램을 함께 돌리면서
개발한 경험이 있으실겁니다.
그런 방식을 체계화 명문화한것이 TDD인데,
좀 더 효율적인 방식으로, 전문적인 유닛테스트 프레임워크를 사용하거나
직접 만든 테스트용 스크립트를 사용하거나, 아니면 개별 스크립트로 만들어 사용하거나 하는 방식이었겠죠.

나머지 질문하시는 내용은 인터넷 검색해보시면 줄줄이 나오니 직접 찾아보시길.

neocoin의 이미지

말씀 중에 TDD 와 Unit Test 의 개념을 섞어서 말씀하시는 것 같습니다. 거기에 자동화된 테스트와, 회귀 테스트도 함께 말씀하셔서 말씀하시는 TDD의 범주가 모호해 지네요.

말씀의 Unit Test 를 지키는 그룹은 많을지도 모르지만, TDD가 이야기하는 Test First Development 를 지키는 그룹은 그 중에서도 극히 드물겁니다.

--------------

그리고 이하는 제 의견입니다.

전 일단 Unit Test를 지키는 그룹도 드물고, 통합된 Unit Test으로 회귀 테스트를 하는 집단도 드물다고 봅니다. 왜냐하면, 회귀 테스트가 필요한 집단은 보통 버전 기반으로 전체 솔루션을 지속적으로 개발해 나가는 업체여야 하는데, 일회성 SI가 많고 그외에는 단기 프로젝트에 일정에 자동화된 테스트 코드까지 기간에 잡히지 않는 개발 문화가 많아서 테스트를 유지 하는 집단은 드물다고 생각합니다.

그래서 대형 포탈의 경우 품질을 올리고 버그를 찾기 위해 인력을 바탕으로 테스팅 그룹을 운영하는게 일반화 되어있다고 생각합니다.

TDD는 해보면 해볼수록 어렵다는 생각을 지울수가 없습니다. 아직 저는 답이 없네요.

creativeidler의 이미지

그리고 Test First를 하는 그룹 중에도 그걸 정말 생산성 향상에 도움이 되게 이용하는 그룹은 더더욱 드물죠.

근데, 사실 TDD를 위해 기간을 별도로 잡아야 한다는 건 좀 이상하죠. 생산성이 향상되기 때문에 TDD를 하는 건데, 결과적으로 프로젝트가 더 늦게 끝나야 한다면 TDD를 할 이유가 없죠. 물론 3개월 짜리 프로젝트를 위해서 테스트 프레임웍까지 개척해야 한다면 TDD가 오바질일 가능성이 높지만, 웹이나 iOS처럼 TDD가 개척된 분야에서는 단기 프로젝트라도 TDD로 개발 기간내에 생산성 향상의 이득을 충분히 누릴 수 있다고 봅니다.

제가 그래서 TDD에 대해 종종 이렇게 이야기하곤 하죠.

"TDD의 이득을 일주일 후에 얻으려고 하지 말라, 30분 안에 TDD의 이득을 얻지 못한다면 TDD를 하지 않는 게 이득이다."

라고...

neocoin의 이미지

안녕하세요. 하하 ;;

단기의 정의가 달라서, 말씀드리기 고민이 되는 부분입니다. 저에게 단기란 개발 기간 1주일에서 1개월 입니다. 이 개발 시간내에서 모든 로직에 Test 붙여나가면서 진행한다면 글쎄요. 확신이 없습니다.

그래서 차후 버전이나 지속적 유지 관리를 위한 제품이라면 Test 자동화를 위한 노력을 들여야하고 이부분을 고려해 더 많은 시간이 산정되어야 한다고 생각합니다.

특히 말씀하신 iOS 에서 부분적으로 그게 너무 어렵게 느껴집니다. (비동기, Canvas Drawing 검증, Network 통신부 등등)

Web 쪽은 View 쪽의 변경 요구 사항이 기존 Test 코드들을 쓰레기로 만들어 버리는걸 보면서 고민이 됩니다. ;;

마지막으로, 제가 30분 안에 느끼는 테스트 코드의 이득은 생산성 향상이라기 보다 그냥 자기 만족이 대부분이었습니다. 그래서 마지막 말씀에 동의하기 어렵습니다. 통상 한 1, 2주일 후에 테스트 코드들이 회귀 테스트를 해주면서 다른 코드들의 버그나 사이드 이펙트 방지 해주면서 생산성 향상을 느끼는 정도였죠.

그외 극적인 도움은 라이브러리나 프레임웍 버전을 바꿀때 였는데, 여태 도움 받은게 기억으로는 5년전에 한번이었습니다. 그래서 좀 짜증이 납니다. ;;

creativeidler의 이미지

네, 저도 1주일 정도면 TDD를 하지 않고, 1개월이면 아마 부분적으로 어려운 부분만 TDD를 할 것 같습니다. 3개월이라면 테스트 프레임웍이 제대로 있는 경우는 하고, 아니면 안할 듯.

저는 보통 Acceptance Test와 Unit Test를 엄격히 나누고, 보통 ATDD를 합니다. 그러면 개발 중에 반복적으로 테스트를 돌리는 시간을 줄여주는 것만으로도 즉각적인 이득을 얻을 수 있죠. 물론 Selenium이나 UISpec 등의 UI 테스트 자동화 도구에 익숙해져 있어야겠지만요. 어쨋든 개발하면서 수동으로 버튼 눌러보는 시간을 줄여주는 것만으로도 테스트 작성에 드는 시간보다 훨씬 많은 시간을 절약할 수 있습니다. 사실 전 자동화 테스트의 가치가 suite를 돌릴 때보다, 기능 개발하는 중에 test method 하나를 돌릴 떄가 더 크다고 봅니다.

그리고, 부수적으로 얻는 효과로, 이렇게 작성된 AT는 대개 UT보다 더 좋은 회귀 테스트가 됩니다.

Unit Test는 대개 설계하기 어려운 문제만 합니다. 머리 속에 설계가 떠오른다면 테스트 없이 그냥 만들죠.

사실 저는 TDD가 처음부터 재밌고 좋았지만, 정말 생산성 향상에 도움이 되는지는 끊임없이 의문이 있었습니다. 그래서 다양한 각도로 TDD를 실험해보고, 각종 지표를 뽑아보면서 측정도 해보면서 TDD는 쉽지만 TDD가 생산성을 높이게 만들기는 아주 어렵다는 생각을 했습니다. 그런 의미에서 neocoin님의 TDD가 어렵다는 말씀에 아주 공감하구요. 하지만, 이제는 방향을 잡은 느낌입니다. 어쨋든 TDD를 위해 많은 시간 투자를 하고 나중에 뽑아내야지..하는 식보다는, 어떻게 하면 TDD로 바로 이득을 취할 수 있을까 하는 방향으로 고민했던 것이 도움이 되었던 듯.

익명 사용자의 이미지

TDD의 본질은 버그없는 작동단위에 대한 빠른 피드백 그리고 그 피드백을 통한 보다 효율적인(?) 개발이라고 봅니다.

그게 체계화되고 활자화되다보니 되려 복잡해보이게 되어버렸지만
내가 원하는 작업이 목적에 부합하게 프로그램이 작동하기 위해 통과해야 하는 여러 테스트유닛을
만들어나가는 과정이기도 하며, 테스트유닛만 잘 작성하더라도 개발을 좀 더 쉽게 할 수 있다는 것인데...
"TDD가 A다" 혹은 "TDD가 B다"라는 단순한 명제는 존재하지 않는다고 봅니다.
TDD는 이런 것이라고 못박는게 별 의미 없다는 말입니다.
그런 grand unification가능한 TDD는 존재하지도 않는다고 봅니다.
----
저같은 경우는 코드를 만든 후에 그 코드안에 foobar_test()와 같은 서브루틴을 같이 넣어두는 편입니다.
간단한 코드를 만들때는 유닛테스트 프레임워크같은게 오히려 불편한 것 같고 덩치큰 무엇을 싫어하는 편이라서..

TDD가 어렵다기 보다는 TDD를 할 수 있는 방식이 한가지만 있지 않고,
목적에 따라서 TDD를 어떤 방식으로 구사하느냐는 전적으로 개발자/혹은 개발팀의 의지에따라서 달라질 수 있고,
어떤 상황에서나 비교적 쉽게 적용할 수 있는 TDD방식을 찾아서 해당 프로젝트에 대해서 조금씩 적용해 나아가면
(이러한 step by step을 밟는 것이 바로 TDD적인 개발방식이죠)
예를 들어 가장 많은 버그를 지속적으로 양산하는 코드에 대해서만이라도 유닛테스트를 먼저 작성하고
TDD를 조금씩 적용해 나아간다면 TDD의 효과를 충분히 볼 수 있다고 생각합니다.
잘 돌아가는 프로젝트를 TDD에 억지로 맞추려고 하지 말고
TDD를 적용하기 쉬운/TDD가 필요한 부분을 찾아서 조금씩 적용해보는 것이
TDD 개발 철학에 맞는 방식이라는 생각입니다.

neocoin의 이미지

자칫 제 글이 너무 까딸스럽게 비춰질 것 같지만, 아쉬운 마음에 적습니다.

다시 말씀드리지만, 그럼 다른 용어를 사용하시면 됩니다. 위에 경우에는 '테스트 자동화 (Test Automation)'나 '유닛 테스트(Unit Test)를 이용한다.' 정도면 적절한 표현이라고 생각합니다.

말씀하신 본질에 대헤서는 공감합니다. 그런데, 테스트 주도 개발 (TDD - Test Driven Development)는 이 용어를 제시하신 분(Kent Beck)께서 그 과정을 좀 더 명확하게 정의해 놨습니다. ( ref http://en.wikipedia.org/wiki/File:Test-driven_development.PNG ) 애초 Test First Development 였다가, 좀 더 프로젝트에 맞게 TDD 라는 말로 발표했습니다. '로직의 구현 이전에 테스트를 먼저 작성해서 테스트가 개발을 이끄는 방법'이라는 핵심 가치와 개념은 당시 매우 신선하고 혁신적이었습니다. 그래서 기존에 Assert 를 통한 코드 내의 유효성 검사(Validation Check)나 테스트 자동화(Test Automation)와 TDD는 명확히 구분됩니다.

익명 님께서 개인의 개발 경험과 철학 속에서 테스트 주도 개발(TDD)의 용어를 사용하시는건 큰 무리 없다고 봅니다. 특히 저도 로직을 구현하고 테스트를 붙이고 다음 개발을 이어나가는 것에 대해서 'TDD가 아니다' 라고 부정할 생각은 없습니다.

왜냐면, 저도 익명님과 비슷하게 작업하며, 그 과정을 TDD라 하지 않고 'TDD를 하려고 노력한다.' 정도로 생각하며 타인에게는 그냥 부분적 tdd한다고 이야기 합니다. 그러나 이렇게 많은 분들이 읽는 곳에서는 명학하게 이야기하려 노력합니다.

(저도 개발 중에 정말 테스트 주도로 개발(TDD)하기도 하고, 작업후에 테스트를 붙이기도 합니다. 이 경계는 확실합니다. 빈도를 따져 볼때 저는 테스트 작성보다 로직을 먼저 구현하는 비중이 훨씬 높습니다. 그래서 TDD라고 말하지 않는 거죠. 테스트가 절 이끌어 주지는 않더군요. 저에게 TDD는 정말 너무 어렵습니다. )

제가 너무 원리적인 부분을 말씀드리는건 저는 처음에 TDD를 '자동화 된 테스트와 함께하는 프로그래밍'로 넓은 범위로 이해했고, 책이나 토론을 통해서 좀더 정확한 저자의 의도를 알아서 머리를 탁치며 반성한 적이 있기 때문입니다. 그래서 넓게 이야기 하는 것을 경계합니다. 자동화된 테스트의 노력은 다양한 형태로 TDD 등장 이전에 사례들이 소개 되었습니다. 유닛 테스트로 불리기전에 마치 우수한 프로그래머 들의 비기처럼 책에 소개 되기도 하였습니다.

그래서 이 쓰레드를 읽는 분들이 함께 생각할만한 주제라고 봅니다.

semmal의 이미지

테스트를 하려면 먼저 하려고 하는 일을 명확히 하고, 그 결과 또한 예측이 가능해야 합니다.
이렇게 명세(or요구사항or개발백로그)가 제대로 만들어지지 않으면 아마 TDD를 쓰기 힘들 겁니다.
어떤 경우에도 불명확한 것을 테스트할 수는 없습니다.

반대로 TDD를 잘 쓰도록 노력하다보면 명세가 제대로 될 수도 있겠지요.
TDD 관련 책을 보더라도 TDD 자체를 설명하기 보다는, (당연히도) 어떻게 잘 쓰는가에 집중하는 경향이 있는 것 같습니다.
하지만 테스트 케이스를 작성하려고 노력하는 것보다는, 먼저 명세부터 제대로 잡아놓는 것이 TDD를 더 쓰기 쉽게 만들어준다고 생각합니다.

문제는 저도 제가 무엇을 만드는지 잘 모른다는 거죠.
만들고 나서야, "아... 내가 이것을 만들었구나." 합니다.

TDD에 대해 개인적으로 느끼는 감상은, 그래서 마치 Objec-Oriented가 밥먹듯이 주장하는 "재사용"과 비슷한 느낌이 납니다.
말은 다 좋지만 다 만들기 전에는 무엇이 언제 어떻게 재사용되는지 알 수가 없거든요.

결론적으로 제 생각에는, 경험이 아주 많아서 생전 처음 만드는 것도 이전에 만들었던 프로그램의 조합처럼 느껴지지 않는 다음에야, 처음부터 TDD나 재사용에 기반한 코드는 작성하는게 아니라는 겁니다.
먼저 예광탄 코드든 프로토타입이든 먼저 작성해본 다음에, 내가 무엇을 만들지에 대해서 확실한 방향과 결과를 설정한 다음에야 쓸 수 있다고 봅니다. (확실한 방향이라는게 프로젝트까 끝날때까지 변하지 않는 방향을 말하는게 아닙니다. 단순히 한 개발기간에만 변하지 않는 정도로 충분하죠.)

하지만 현실은, 프로토타입이 그대로 납품되는게 현실이므로... 비겁한 변명을 해봅니다.

------------------------------
How many legs does a dog have?

익명 사용자의 이미지

> (...)
> 결론적으로 제 생각에는, 경험이 아주 많아서 생전 처음 만드는 것도 이전에 만들었던 프로그램의 조합처럼
> 느껴지지 않는 다음에야, 처음부터 TDD나 재사용에 기반한 코드는 작성하는게 아니라는 겁니다.
> (...)

자신이 방금 500여줄의 간단한 코드 A를 만들었다고 칩시다. 이게 잘 돌아가는지 어떻게 알 수 있을까요?

1) A라는 코드가 잘 돌아가는지 alpha테스트코드가 통과되면 A가 완벽하다고 생각한다.
2) alpha가 제대로 통과하지 않으면 A를 고친다.
3) alpha를 통과하려면 beta라는 테스트코드를 따로 만드는게 유리하면 beta테스트코드를 분리한다.
4) alpha/beta가 모두 통과하면 A가 완결된 것으로 생각한다.

이런 식으로 코드를 만들고 코드에 해당하는 테스트코드가 통과하면 다음 단계로 넘어가는 방식이 바로 TDD라고 알고 있습니다. "개발 *초기*부터 혹은 개발하면서 *지속적*으로" 테스트 코드를 만드는 개발론이 TDD라는 겁니다.

semmal의 이미지

그 질문에 답하려고 하면 다음과 같은 문제가 해결되어야 합니다.

무엇을 만드는지 누가 알고있습니까?
개발은 누가 지시합니까?
잘 돌아가는지 누가 결정합니까?

먼저 프로그램의 이름은 정해져있는데, 일단 프로그램을 요구하는 고객도, 개발하는 개발자도 무엇을 개발해야할지 모릅니다.
때문에 개발중에도 요구사항(말 그대로 요구하는 사항)이 바뀌는 경우는 허다합니다.

다음은, 요구사항이 정해지지도 않았는데, 고객이든 보스든 일단 무조건 보여달라고 합니다.
제대로 안돌아가도 됩니다.
어떻게 돌아가는지 일단 보고 결정하자는 것이죠.

마지막으로, 일단 돌아가는 것을 봤으니, 이러이러한 기능을 거기에 추가해달라고 합니다.
물론 이 기능은 다음날에도 바뀔 수 있습니다.

애초에 정리되지 않은 설계에다 이런저런 단발성 코드를 덧붙이고, 잦은 구조변경으로 인해서 돌아가다가 죽어도 됩니다.
그런 버그는 갑은 프로토타입만 개발해도 벅찬 시간을 주니 개발자는 시간이 없어서 못고치고
갑 담당자는 프로젝트 실패한거 들키면 인사고과에 영향을 받기 때문에 일단 넘기자는 주의 입니다.

자, 이 프로젝트에 "*초기*부터 *지속적*으로" 테스트 코드를 어떻게 만드는지 예를 들어 주실 수 있을까요?

TDD가 뭔지 몰라서 안하는게 아니랍니다.

------------------------------
How many legs does a dog have?

cocas의 이미지

제가 보는 TDD는 소프트웨어 개발 과정에서 문서로 된 명세는 작성하지 못하더라도 최소한 테스트를 작성해서 소프트웨어가 뭘 해야 할지는 개발자가 생각해보고, 명확하게 하자는 것입니다. 아무리 뭘 개발해야 할 지 명확하지 않다 해도 개발자가 생각하는 모습이 있을 것이고 그걸 구현하기 위해 코드를 작성할테니까요. 그렇다고 원리주의적으로 '반드시 테스트부터 작성해야 한다' 라던가 '모든 경우의 테스트가 필요하다' 라고 생각하지는 않고요. 개발하는 소프트웨어의 종류에 따라 유연하게 대처해야겠지만 아직 경험이 짧아서 구체적으로 어떻게 대처해야 하는지는 잘 모르겠습니다.

semmal 님이 예로 드신 경우는 사실 테스트를 할 필요가 과연 있을까 의문이 되는 상황입니다. 안타깝지만 실제로 현실이기도 하고요. 버그가 발생해도 시간이 없어서 못 고치고, 발주자는 버그가 있어도 일단 넘기는데 가뜩이나 비싼 소프트웨어 테스트의 ROI 가 나오기가 어렵죠. 소프트웨어 테스트가 ROI가 안 나올 상황이면 TDD 역시 할 이유가 없겠고요.