Octoping의 블로그
article thumbnail
 

테스트 주도 개발 | 켄트 벡 - 교보문고

테스트 주도 개발 | 테스트 주도 개발은 테스트가 개발을 주도하는 방법이다. 테스트가 개발을 주도한다는 것은 테스트가 코딩의 방향을 이끌어 간다는 말이다. 테스트를 실패하는 코드가 없으

product.kyobobook.co.kr

들어가기 앞서

켄트 벡의 유명한 저서, 테스트 주도 개발을 읽었다.

평소에 테스트의 의미와 중요성에 대해서는 깊은 이해를 하고 있다고 생각했다. 그렇다면 TDD는 어떤 의미를 가지고 어떤 방식을 통해 구현되는 것일까?

항상 궁금증은 있었지만 궁금증을 해결해 볼 기회는 없었는데, 이번에 현 직장의 현 직원 분들과 전 직원 분(퇴사하신 분들.. ㅋㅋ)들 총 여섯 명이서 TDD에 대해 스터디를 모집하게 되어 공부해 볼 수 있게 되었다. 뜻깊은 시간이었다.

Test-Driven-Development이란?

테스트 주도 개발이란, 어떤 기능을 개발할 때 다음 세 가지의 패턴을 돌아가면서 구현하는 방식이다.

TDD의 세 가지 사이클

  1. 실패하는 테스트 만들기
  2. 테스트를 성공시키기 위해 기능을 최대한 빠르게 만들기
  3. 구현한 코드의 중복을 제거하기

언뜻 보면 간단한 방법이고, 실제로 이 방법론을 적용하면 복잡한 프로그램을 구현할 수 있다는 사실이 믿기지 않기도 한다. 나 또한 그랬고, 정말 이 Test-Driven-Development라는 마법이 어떻게 돌아가는 것인지 궁금해서 이 책을 구매하게 되었다.

Why Test-First?

나는 TDD의 사이클에서 가장 중요한 것은 ‘실패하는 테스트 만들기’라고 생각한다. 그렇다면 왜 기능을 개발한 후에 내가 만든 기능이 잘 돌아가는지 확인하기 위해 테스트를 작성하는 것이 아니라, 테스트를 작성한 후에 기능을 개발하는 것일까?

*TDD의 아이러니 중 하나는 TDD가 테스트 기술이 아니라는 점이다(워드 커닝엄의 선문답이다). TDD는 분석 기술이며, 설계 기술이기도 하다. 사실은 개발의 모든 활동을 구조화하는 기술이다.
- Kent Beck

 

TDD는 테스트 코드를 잘 작성하는 방법론도 아니고, 테스트 기술조차 아니기 때문이다!

TDD는 분석 기술이자, 설계 기술이기도 하며, 개발의 모든 활동을 구조화하는 기술이다.

알고리즘을 열심히 풀어본 사람이라면 분할 정복(Divide and Conquer)이라는 키워드를 들어본 적 있을 것이다. 거대한 문제를 해결하기 위해 작은 문제 여러 개로 분할하여 해결하는 Bottom-Up 방식인데, 그렇다면 큰 문제를 작은 문제로 분할할 때의 기준은 어떻게 되는 것일까?

TDD는 이 기준을 테스트 코드로 잡는다. 내가 작성하는 이번 테스트 코드가 이번에 내가 해결해야 할 하나의 작은 문제가 되는 것이다.

테스트 코드가 왜 큰 문제를 분할하는 기준이 되는 것일까?

테스트 코드는 given, when, then 이라는 세 가지 구조를 통해 구성된다.

  1. 어떤 특정한 파라미터가 주어지고 (given)
  2. 이 함수가 이런 파라미터를 받아서 실행되었을 때 (when)
  3. 결과가 이렇게 나와야 한다 (then)

 

“이런 값을 받아서 이 함수를 실행했을 때 결과가 이렇게 나와야 한다."

이것보다 더 함수의 역할을 잘 설명하는 문장이 있을 수 있을까?

테스트 코드를 먼저 작성한다는 것은 그 자체로 내가 이번에 해결해야 할 문제의 명세를 뚜렷하게 구체화하는 것이다.

책의 구성

테스트 주도 개발 책은 크게 3개의 장으로 이루어져 있다.

1장은 TDD를 활용하여 단일 통화(Currency)의 계산을 다루는 프로그램에서 다중 통화의 구현과 계산을 다루도록 개선하는 과정을 단계마다 소개하며 보여준다.

2장은 TDD를 활용해서 xUnit을 직접 구현하는 과정을 보여준다.

3장은 테스트 주도 개발을 할 때 적용할 수 있는 여러 패턴과 명심할 점을 짚어준다.

개인적으로는 1, 3장을 주의 깊게 읽었다.

실무에서 사용할 수 있을까?

백엔드 같은 로직 구현 위주의 프로젝트에 있어서는 TDD를 충분히 사용할 수 있다고 생각한다. 이는 실제로 켄트 벡이라는 산 증인이 지금 이 순간까지도 TDD를 열심히 사용하고 있기도 하고.

하지만 프론트엔드나 앱 개발 같은 GUI가 낀 프로젝트의 경우 어떨까?

 

물론 프론트엔드에서 TDD가 가능하다는 것을 보여드립니다.라는 명 세션이 있는 것, 안다. 하지만 이 세션에서도 로직이 실행됨에 있어서 ‘어떤 텍스트가 뜬다’라는 것에 대해서만 테스트를 작성하는 것에 그치고 있다.

instagram @waterglasstoon

도메인과 뷰 로직의 분리를 통해서 도메인 로직은 테스트 할 수 있다. 이 부분은 TDD로 충분히 구현이 가능하다.

하지만 CSS와 같은 순수 뷰 모델은 어떻게 테스트할 수 있을까? Jest(Javascript의 테스팅 프레임워크)에서는 스냅샷 테스트 (기존에 저장해둔 스냅샷과 현재 실행했을 때의 스냅샷의 생김새가 다를 경우 테스트 실패)를 지원하고 있지만 Test-First인 TDD에서는 이 마저 불가능하다.

“우리는 GUI를 위한 테스트를 많이 작성하지는 않았습니다. 대부분의 테스트를 GUI 밑의 엔진을 위해 작성했고, 모든 요소가 제대로 연결되었는지 확인하기 위해 단지 몇 개의 GUI 테스트만 작성했습니다”

- Kent Beck (‘테스트 주도 개발’ 책의 한국어판 인터뷰 중)

 

물론 이건 TDD 자체의 한계가 아니라 뷰 모델의 테스트의 어려움으로 인한 이유이긴 하다.

정리하며

테스트 주도 개발은 만능이 아니다. 테스트 주도 개발을 사용한다 하여 모든 버그를 막아줄 수 있는 것도 아니며, 원래라면 할 수 없었던 좋은 설계를 하게 해주는 것도 아니다.

하지만 테스트 주도 개발은 우리가 구현해야 할 거대한 문제를 잘게 쪼갤 수 있는 기준을 주고, 그 부산물로 발생하는 테스트 코드는 우리의 프로젝트가 커지면서 수행해야 할 리팩토링을 거리낌 없이 수행할 수 있도록 든든한 뒷받침이 되어준다.

앞으로 진행하는 프로젝트들은 최대한 TDD를 활용하며 진행해보려고 한다.

profile

Octoping의 블로그

@Octoping

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!