알라딘MGG와이드바


단위테스트(UnitTest, xUnit) 관련 질문 있으시면 해 주세요 #2 개발 이야기

안녕하세요. 9월 초에 있을 KGC(Korea Games Conference) 발표 준비 할겸해서 이것저것 알아보고 있습니다.
마침 올해 제가 번역한 '[http]xUnit 테스트 패턴' 과 '[http]Debug It! 실용주의 디버깅' 도 나온터라 주제를 '낡은 코드와 단위테스트'로 잡아보았습니다.
2007년 KGC 에서 제가 '[http]TDD, UnitTest for games' 를 발표할 당시에만 해도 단위테스트를 모르는 사람도 꽤 있었지만, 지금은 단위테스트가 많이 알려졌고 실제로 단위테스트를 하고 있는 조직도 많이 늘었습니다. 하지만, 많은 분들이 레거시 코드에 단위테스트를 도입하면서 어려움을 겪고 있고, 그러다보니 단위테스트가 별로 도움이 안 되는 거 아니냐는 의견도 많이 들었습니다. 그래서 이번에는 오래된 코드 기반에 단위테스트를 도입하는 기법과 팁을 주로 다뤄볼 생각입니다.

이메일을 통해서 단위테스트에 대해 물어보시는 분들이 있어서 허락을 받고 여기에 질문과 답변을 올립니다. 다른 분들도 단위테스트를 만드면서 궁금했던 점 있으시면 댓글이나 이메일, [http]위키 등으로 질문을 올려주시면 정리해서 블로그에 올려놓도록 하겠습니다.

단위테스트를 만드는 철학은 사람마다 호불호가 다릅니다. 제가 개인적으로 경험하고 느낀 점에 기초해서 답변해 드리겠습니다.

Jiwon
단위테스트의 프로젝트간 재활용은 어떻게 되나요? 단위테스트 프레임웤을 프로젝트 때마다 새로 만들거나 커스터마이징하는 노력은 어느정도인가요? 단위테스트의 단위규모는 보통 어느정도로 잡고 어떤 기준을 따르나요?

답변
보통 프로젝트가 다를 경우 테스트 케이스도 전혀 다르기 때문에 단위테스트를 재활용하는 경우는 거의 없었습니다. 단위테스트 재활용이 필요하다고 느낄 경우에는, 둘 중 어느쪽이 좀 더 기반클래스인지를 살펴본 뒤에 둘 중 하나에만 테스트를 추가했습니다.
단위테스트 프레임워크는 UnitTest++ 와 googletest 를 써 보고 있는데 둘 다 프로젝트가 잘 되어 있고 구성도 비슷하기 때문에 더 추가할만한 내용이 별로 없었습니다. 프레임워크 붙이는 것도 직접 해 보시면 10-20분만에 하실 수 있습니다. 프레임워크에 직접 추가한 거라면 CHECK_CLOSE 류의 함수같은 게 있겠네요. 예를 들면 Vector 라는 클래스가 있고 멤버변수로 float 형의 x, y, z 가 있다고 해 봅시다. Vector 클래스가 서로 같은지를 비교하려면 CHECK_CLOSE(vector1, vector2, 0.01); 과 같이 (부동소수점 오류 때문에) 얼마간의 오류 margin 을 허용해 줘야 합니다. 이런 것을 맞춤 단언문(Custom Assertion) 이라고 합니다(xUnit 테스트 패턴, p.615). 이런 것 외에는 단위테스트 프레임워크를 그대로 사용할 수 있었습니다.
단위규모는 작은 것부터 크게 만들어 갔습니다. 처음에는 CHECK_EQUAL(true); 만 검사하는 가장 간단한 테스트가 잘 실행되는지를 확인합니다. 그 다음에는 가장 의존관계가 없는 최상위 base 클래스나 static 메서드부터 테스트를 만듭니다. 그리고나서는 자주 사용하는 클래스 객체를 만들 수 있는 테스트를 만듭니다. 점점 늘려가서 나중에는 QA 팀에서 보내준 버그report 의 재현방법을 그대로 코드로 만들 수 있는 정도까지 범위를 늘렸습니다.

세영
유닛테스트 프로파일 재활용이나 테스트 결과들을 어떻게 정리&발전시키는지 궁금합니다.

답변
'유닛테스트 프로파일 재활용'은 무슨 뜻인지 몰라서 알려주시면 다시 정리하도록 하겠습니다.
테스트 결과는 1일~1주일 간격으로 테스트 전체 갯수, 실행에 걸리는 시간을 측정해 wiki 에 정리했습니다. 시간 측정이 중요한 이유는 두 가지가 있습니다. 하나는, 시간이 너무 오래 걸리면 개발팀에서 싫어하기 때문에 항상 적정한 시간을 유지하려고 했습니다. 예전 프로젝트에서는 최대 1,500 개 가량의 테스트가 실행되는데 걸리는 시간을 10초 안팎으로 유지했었습니다. 두 번째로 시간이 너무 오래 걸리거나 너무 빨리 끝난다면 뭔가 잘못된 것이 있다는 것을 알려주는 신호로 사용할 수 있습니다.
테스트 갯수 증가 대비 장애 횟수 감소 여부는 버그report 툴에서 XML 로 데이터를 뽑아서 정리했습니다. 덕분에 꽤 의미있는 데이터를 얻어서 다른 분들에게 설득하는 용도로 사용할 수 있었고, ?KGC08 에서도 발표할 수 있었습니다.

중원
단위테스트를 조금씩 실무에서 적용중인데요. 효과를 많이 보곤 있습니다만, 테스트가 점점 많아지다보니, 테스트들 관리도 일이 되더군요. 여기 관련 노하우가 있으시면 공유 부탁드립니다. (__)

답변
'xUnit 테스트 패턴' 책에 잘 나와있습니다 ㅎㅎ. 제 경험에서 말씀드리자면, 테스트가 늘어나면서 픽스처(Fixture) 가 점차 정교해졌습니다. 중복되는 루틴을 픽스처의 멤버함수로 만들고, 생성함수도 추가하고, 리소스 누수 여부를 검사하는 루틴도 픽스처의 tearDown 메서드에 추가하는 식으로 픽스처의 기능이 점점 늘어나더군요. 테스트도 하나의 프로젝트 코드라고 생각하고 제품코드와 같은 정도의 노력으로 리팩토링을 계속 해 줘야 합니다. 그 다음으로 Suite 를 계층별로 나누었습니다. 저는 Suite 를 ?NewTest, ?AllTest, ?LongTimeTest 와 같이 나눠서 현재 제가 작업중인 테스트는 ?NewTest Suite 에 둬서 실행하면 그 테스트부터 실행되게 했습니다. 그리고 check-in 하기 전에 ?AllTest Suite 에 있는 테스트를 돌려서 회귀 문제가 생기지 않게 했고, CI 에서는 ?LongTimeTest 까지 같이 돌리게 했습니다.

http://www.freefoto.com/images/13/44/13_44_58---Scaffolding_web.jpg

덧글

  • 한주영 2010/08/18 15:08 # 삭제 답글

    Q: 단위테스트의 프로젝트간 재활용은 어떻게 되나요?

    이 질문은 저희 회사에서도 늘 나오는 내용이고 여기에 제가 답했던 내용을 여기에 공유할까 합니다.

    제 답은.. "단위 테스트 코드의 재활용은 해당 코드의 재활용과 같다", "단위 테스트 코드의 생명은 그것이 테스트하는 프러덕션 코드의 생명과 같다" 라는 것입니다.

  • 박PD 2010/08/19 08:34 #

    오우... 좋은 얘기입니다. 감사합니다.
댓글 입력 영역


Yes24위대한게임의탄생3

위대한 게임의 탄생 3
예스24 | 애드온2