백엔드 Back-end/테스트 Test

Q. 테스트 주도 개발Test-Driven Development(TDD)란?

Tap to restart 2023. 5. 30. 01:00

A. 켄트 벡이 창시한 개발 방법론으로 테스트부터 작성하는 개발 방법론이다.

먼저 통과하지 못할 테스트를 작성하고 테스트를 통과하도록 코드를 작성한다. 그 뒤 코드를 개선, 리팩터링하고 테스트하는 과정을 반복하는 식이다.

 

테스트 주도 개발

테스트 주도 개발의 목표

작동하는 깔끔한 코드(clean code that works). 론 제프리즈(Ron Jeffries)의 핵심을 찌르는 이 한마디가 바로 테스트 주도 개발의 궁긍적인 목표다.

출처: 켄트 벡, 「테스트 주도 개발」, 김창준, 강규역 역, (주)도서출판인사이트, 2005, 21p.

 

테스트 주도 개발의 규칙

테스트 주도 개발에서는
● 오직 자동화된 테스트가 실패할 경우에만 새로운 코드를 작성한다.
● 중복을 제거한다
는 두 가지 단순한 규칙만을 따른다.

출처: 켄트 벡, 「테스트 주도 개발」, 김창준, 강규역 역, (주)도서출판인사이트, 2005, 22p.

 

테스트 주도 개발의 프로그래밍 순서

1. 빨강 - 실패하는 작은 테스트를 작성한다. 처음에는 컴파일조차 되지 않을 수도 있다.
2. 초록 - 빨리 테스트가 통과하게끔 만든다. 이를 위해 어떤 죄악을 저질러도 좋다.
3. 리팩토링 - 일단 테스트를 통과하게만 하는 와중에 생겨난 모든 중복을 제거한다.
빨강/초록/리팩토링은 TDD의 주문과도 같은 것이다. 

출처: 켄트 벡, 「테스트 주도 개발」, 김창준, 강규역 역, (주)도서출판인사이트, 2005, 23p.

 

유명 개발자들이 추천하는 개발 방식

마틴 파울러

리팩터링 책으로, 제어 역전(Inversion of Control)과 의존성 주입(Dependency Injection) 등 용어로 유명한 마틴 파울러도 추천하는 개발방식이다. 리팩터링 책에 나온 관련 구절을 살펴보자.

사실 다른 사람에게 이런 식으로 개발하라고 설득하기는 녹록지 않다. 테스트를 작성하려면 소프트웨어 제품 본체 외의 부가적인 코드를 상당량 작성해야 한다. 그래서 테스트가 실제로 프로그래밍 속도를 높여주는 경험을 직접 해보지 않고서는 자가 테스트의 진가를 납득하긴 어렵다. 게다가 테스트 작성법을 배운 적이 없는 프로그래머가 많을뿐더러, 테스트에 대해 생각조차 못 해본 이도 많다. 테스트를 수동으로 하면 좀이 쑤실 정도로 지겹다. 하지만 자동화한다면 테스트 코드를 작성하는 재미가 꽤 쏠쏠하다.
테스트를 작성하기 가장 좋은 시점은 프로그래밍을 시작하기 전이다. 나는 기능을 추가해야 할 때 테스트부터 작성한다. 얼핏 순서가 뒤바뀐 듯 들리지만, 전혀 그렇지 않다. 테스트를 작성하다 보면 원하는 기능을 추가하기 위해 무엇이 필요한지 고민하게 된다. 구현보다 인터페이스에 집중하게 된다는 장점도 있다(무조건 좋은 일이다). 게다가 코딩이 완료되는 시점을 정확하게 판단할 수 있다. 테스트를 모두 통과한 시점이 바로 코드를 완성한 시점이다.
켄트 벡은 이처럼 테스트부터 작성하는 습관을 바탕으로 테스트 주도 개발Test-Driven Development(TDD)이란 기법을 창시했다. TDD에서는 (처음에는 통과하지 못할) 테스트를 작성하고, 이 테스트를 통과하게끔 코드를 작성하고, 결과 코드를 최대한 깔끔하게 리팩터링하는 과정을 짧은 주기로 반복한다. 이러한 테스트-코딩-리팩터링 과정을 한 시간에도 여러 차례 진행하기 때문에 코드를 대단히 생산적이면서도 차분하게 작성할 수 있다. TDD에 대해서는 여기서 자세히 설명하지 않지만, 내가 프로그래밍하는 방식이자 추천하는 방식이다.
이 정도면 테스트가 중요한 이유를 충분히 설명한 것 같다. 자가 테스트 코드를 작성하면 누구나 효과를 볼 수 있다고 굳게 믿지만, 이 책의 주제는 어디까지나 리팩터링이다. 리팩터링에는 테스트가 필요하다. 그러니 리팩터링하고 싶다면 테스트를 반드시 작성해야 한다.

출처: 마틴 파울러, 「개정판 | 리팩터링(2판)」, 이복연, 남기혁 역, 한빛미디어(주), 2020, 134p.

리팩터링 책 자체에 기여자로 켄트 벡이 명시되어 있다. 1999년에 출판된 리팩터링 책 초판에도 명시되어 있다.

리팩터링(2판) 표지(출처: 아마존)
리팩터링 초판(출처: 구글 도서)

로버트 C 마틴

클린 시리즈 책으로, SOLID 원칙으로 유명한 로버트 C 마틴도 추천한다. 클린 소프트웨어 책에 나온 관련 구절을 살펴보자.

하나의 단위 테스트를 작성하는 일은 단순한 검증이라기보다는 설계의 문제다. 또한 단순한 검증이라기보다는 문서화의 문제이기도 하다. 단위 테스트를 작성하는 일은 상당한 숫자의 피드백 루프를 마무리 짓는 일이고, 이 중 최소한은 기능의 검증에 속한 것이 된다.

테스트 주도 개발
프로그램을 설계하기 전에 먼저 테스트를 설계하면 어떨까? 어떤 함수가 존재하지 않으면 실패하는 테스트를 만든 다음에 프로그램에서 그 함수를 구현하면 어떨까? 아예 한 줄의 코드도 없어서 실패하는 테스트를 만든 다음에야 프로그램에 그 코드를 추가하는 것은 어떨까? 처음에는 어떤 기능성의 존재 여부를 검사하는 테스트를 작성한 후에 단계적으로 그 기능성을 추가해나가는 것은 어떨까? 이런 방식이 개발하던 소프트웨어의 설계에 주는 효과는 무엇일까? 이 같은 포괄적인 테스트 집합의 존재에서 이끌어낼 수 있는 이점은 무엇일까?
일차적이고 가장 명백한 효과는 프로그램의 모든 단일 함수가 그 동작을 검증하는 테스트를 갖게 된다는 것이다. 이 테스트 집합은 그 이후의 개발을 위한 뒷밤침이 되어, 프로그래머가 기존의 어떤 기능을 부주의하게 망가뜨릴 때마다 그 사실을 알려준다. 프로그래머는 그 과정에서 뭔가 중요한 것을 망가뜨릴 염려 없이 프로그램에 함수를 추가하거나 구조를 바꿀 수 있다. 이 테스트들은 프로그램이 아직 제대로 동작하고 있음을 알려주므로, 프로그래머는 훨씬 자유롭게 프로그램을 수정하거나 개선할 수 있다.
명백하진 않지만 더 중요한 효과는, 테스트를 먼저 작성할 경우 프로그래머가 다른 관점에서 문제를 해결할 수 있다는 것이다. 프로그래머는 작성한 프로그램을 그 프로그램의 호출자 관점에서 봐야 한다. 따라서 프로그래머는 프로그램의 함수만큼이나 인터페이스에도 바로 관심을 가져야 한다. 테스트를 먼저 작성함으로써, 프로그래머는 편리하게 호출할 수 있는 소프트웨어를 설계할 수 있다.

출처: 로버트 C. 마틴, 「클린 소프트웨어」, 이용원, 김정민, 정지호 역, 제이펍, 2020, 34-35p.

 
유명 개발자로 소개한 로버트 C 마틴, 마틴 파울러가 거의 켄트 벡과 같은 생각을 갖고 있다는 것을 확인할 수 있다.
이 세 개발자한테는 공통점이 있다. 모두 애자일 소프트웨어 개발 선언에 참여한 저자들이다.
 

애자일 선언 저자들 목록(출처: https://agilemanifesto.org)