본문 바로가기
개발 공부/Spring

TDD 맛보기 (1) - TDD란?

by 개발인생 2022. 1. 10.
반응형

들어가기

누구나 개발을 하게되면 테스트 코드 , TDD 에 대해 한번쯤은 듣기 마련입니다.

테스트 코드는 개발하는데 있어서 중요한 요소 중 하나입니다.

최근에는 많은 회사에서 테스트 코드, TDD를 적극 도입하고 있는 추세라고 합니다.

이번 포스팅에서는 테스트 코드, TDD에 대해 알아보는 시간을 갖도록 하겠습니다.

테스트 코드

개발을 하면서 우리는 수많은 종류의 테스트를 하게됩니다.

예를 들면, 포스트 맨을 이용한 api 통신 테스트가 있습니다.

심지어는 크롬창을 키고 URL을 입력해 개발한 값을 받아보는 것 또한 테스트에 속합니다.

테스트 코드는 로직 동작하는 방식에 대한 결과를 코드로 검증하는 걸 말합니다.

즉, 로직을 테스트 하는 코드를 테스트 코드라고 합니다.

테스트 코드는 다양한 라이브러리를 통해 작성할 수 있습니다.

대표적인 예로 JUnit , Jest 등이 있습니다.


테스트 코드를 작성하는 이유

테스트 코드 작성에는 여러가지 장점이 있습니다.

리팩토링

리팩토링이란 코드를 좀 더 좋은 방식으로 개선하는 과정을 말합니다.

이렇게 코드를 개선하게 되면 의도지않게 실수를 하거나, 해당 코드를 개선함으로 인해 다른 코드에 영향 이 발생할 수 있습니다.

테스트 코드를 잘 작성했다면 리펙토링을 진행하면서 어디서 오류가 발생했는지 정확히 알 수 있습니다.

내가 리팩토링한 기능이 예전처럼 잘 돌아가는지 확인하기 위해 복잡한 과정없이 예전에 작성해두었던 테스트 코드를 실행만하면 됩니다.

Side Effect

우리는 끊임없이 기능을 추가하고, 유지 보수하고 버그를 잡아내는 과정을 반복합니다.

리펙토링과 같은 맥락으로 기능 추가, 버그를 잡아내는 과정 등에서 생긴 사이드 이펙트를 빠르게 잡아내고

수정할 수 있습니다.

더 좋은 설계

설계가 제대로 되지 않은 소프트웨어라면 테스트 코드 작성에 있어서 굉장한 어려움을 겪게됩니다.

반면, 각 기능들이 논리적인 단위로 적절히 나뉘어져 있고, 각 기능들이 단순하며, 한가지 기능만하게 된다면

자연스레 테스트 코드 작성이 용이해집니다.

테스트 코드는 자연스럽게 좋은 설계로 개발자를 이끌어줍니다.

이 부분은 저도 아직 경험해보지 못했기 때문에 훗날 다시 다뤄볼 예정입니다.


TDD

이렇게 좋은 테스트 코드를 작성하는데 있어서 빠짐없이 등장하는 것이 바로 TDD입니다.

TDD란 Test Driven Development 의 약자로, 테스트 주도 개발 이라고도 합니다.

작은 단위의 테스트 케이스를 작성하고, 이를 통과하는 코드를 추가하는 단계 를 반복하여 프로그램을 구현하는 방법론입니다.

단위 테스트

단위 테스트 란 한 단위만을 테스트 하는 것을 말합니다. 여기서 단위란, 하나의 기능 또는 메서드 입니다.

일반적인 테스트 코드 작성은 단위 테스트 를 의미합니다.

통합 테스트는 테스트 시 모든 컴포넌트들이 구동된 상태에서 테스트를 하게되는데, 캐시, 데이터베이스를 구동하여 실제 연결을 하고

테스트를 하기 때문에 시스템이 커질수록 테스트를 위한 시간이 상당히 커지게 됩니다.

반면, 단위 테스트는 테스트할 부분만 독립적으로 테스트하기 때문에 빠르게 테스트 코드를 통한 피드백을 받을 수 있습니다.

TDD 개발주기

위의 사진은 TDD의 개발주기에 대한 사진입니다.

RED-GREEN-REFACTOR 싸이클 이라고 합니다.

  • RED: 맨 처음 실패하는 테스트 코드를 먼저 작성합니다.
  • GREEN: 테스트 코드를 성공시키기 위해 실제 코드를 작성합니다.
  • YELLOW: 코드를 리팩토링하는 단계입니다.

중요한 것은 실패하는 테스트를 작성할 때까지 실제 코드를 작성하지 않는 것 입니다.

RED: 테스트 실패

구체적인 하나의 요구사항을 검증하는 하나의 테스트를 만듭니다.

이때 추가한 테스트가 실패하는지 확인합니다.

실패하는 것이 확인 되어야, 테스트가 검증력을 가진다고 신뢰할 수 있습니다.

실패의 이유는 운영 코드가 아직 변경되지 않았기 때문 이어야 합니다.

GREEN: 테스트 성공

추가된 테스트를 포함하여, 모든 테스트가 성공하게끔 운영 코드를 변경합니다.

테스트 성공은 모든 요구사항을 만족했음을 의미 합니다.

테스트 성공을 위한 최소한의 코드 변경만 진행합니다.

TDD에서는 테스트 성공을 위한 최소한의 코드 그 이상을 변경하거나 추가하면 안됩니다.

테스트 되자 않은 코드가 중간에 추가되면, 이후 리팩토링 등의 다른 프로세스에서 어떤 부작용을 가져올지

알 수 없기 때문입니다.

REFACTOR: 리펙토링

코드를 정리합니다.

인터페이스 뒤에 숨어있는 구현 설계를 개선 합니다.

F.I.R.S.T

좋고 깨긋한 테스트 코드를 작성하기 위해서는 아래의 5가지 규칙을 따라야합니다.

  1. Fast: 테스트는 빨라야 합니다.
  2. Independent: 각 테스트는 서로 의존하면 안됩니다.
  3. Repeatable: 테스트는 어떤 환경에서도 반복 가능해야 합니다.
  4. Self-Validating: 테스느는 Bool 값으로 결과를 내야합니다.
  5. Timely: 테스트는 적시에 작성해야 합니다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현합니다.

일반 개발 방식과 TDD 개발 방식 비교

일반 개발 방식

보통의 개발 방식입니다.

요구사항 > 설계 > 개발 > 테스트 > 배포 의 주기를 갖습니다.

하지만 위의 방식은 몇가지 문제점이 존재합니다.

  1. 요구사항이 처음부터 명확하지 않을 수 있다.
  2. 처음부터 완벽한 설계는 어렵다.
  3. 자체 버그 검출 능력 저하 또는 소스 코드의 품질이 저하될 수 있다.
  4. 자체 테스트 비용이 증가할수 있다.

고객의 요구사항 또는 디자인 오류 등 많은 외부, 내부 조건에 의해 어느 프로젝트든 초기 설계가 완벽하다고 말할 수 없습니다.

재설계로 인해 개발자는 코드의 삽입, 수정, 삭제 등의 과정을 통해 불필요한 코드가 생기거나 중복된 코드가 늘어날 가능성이 큽니다.

이러한 코드들은 재사용이 어렵고 관리가 어려워져 유지 보수를 어렵게 만듭니다.

작은 부분의 기능 수정에도 모든 부분을 테스트해야 하므로 전체적인 버그를 검출하기 어려워집니다.

그 결과, 작은 수정에도 모든 기능을 다시 테스트해야되기 때문에 소스 코드의 품질 저하와 테스트 비용이 증가하게 됩니다.

TDD

TDD 개발 방식입니다.

일반 개발 방식과의 가장 큰 차이점은 테스트 코드를 작성한 뒤에 실제 코드를 작성한다 는 점입니다.

테스트 코드를 작성하는 도중에 발생하는 예외 사항, 버그, 수정사항들은 테스트 케이스에 추가하고 설계를 개선합니다.

이후 테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성합니다.

이렇게 단위 테스트 작성 > 테스트 실행 > 운영 코드 작성 > 테스트 실행 > 리펙토링 > 단위 테스트 > ..... 를 반복합니다.

반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고, 소스코드는 간결해집니다.


이상 TDD에 대해 간단히 정리해봤습니다.

TDD에 대해서는 읽을 자료도 많고, ATDD, BDD 등 좀 더 다양한 테스트 기법이 있습니다.

테스트 코드에 대해서도 공부할게 참 많은 것 같습니다.

반응형

댓글