[TDD] 테스트 주도 개발

[TDD] 테스트 주도 개발

“해당 포스팅은 드림코딩테스트 코드와 TDD 🧪(feat. 프론트엔드, 백엔드를 위한 테스트 코드)을 참고하여 포스팅하였습니다. 영상을 제작해주신 드림코딩엘리님에게 감사드립니다.”

#목차

TDD(Test-Driven Development)

Test란?

Test란?

  • 개발자들이 말하는 테스트란?
    • 소프트웨어 테스트를 말하며, 애플리케이션 제품이나, 서비스의 품질을 확인하고, 버그들을 찾는데 사용하고 있다.
    • 한마디로 소프트웨어 테스트란, 제품이 원하는 데로 동작하는지 확인하는 것과 애플리케이션이 우리가 원하는 데로 동작하는지 검증하고 확인하는 것이다.
    • 여기서 제품이란, 우리의 메서드, 기능, UI, 성능, API 스펙이 우리가 원하는 데로 동작하는지 확인하는 것이다.


Software Test란?

Software Test란?

  • 우리의 목표가 무엇이냐에 따라서, 우리의 플랫폼과, 환경이 무엇이냐의 따라서 다양한 테스트가 있다.
  • 많은 개발자들이 정말 많이 사용하는 Unit Test부터 Functional Test, Integration Test, Component Test, Contract Test, E2E Test, Performance Test 등등 정말 많은 테스트가 있다.
  • 우리가 뭘 원하느냐, 어떤 걸 확인하고 싶냐에 따라 다양한 테스트들이 있지만 이 테스트들의 프로세스는 딱 하나로 정의할 수 있다.


Software Test Process

Software Test Process

  • 특정한 기능을 수행하는 비즈니스 로직을 가지고 있는 소스코드가 있다면, 그에 해당하는 테스트 코드를 작성한다.
  • 이때, 이 테스트 코드는 우리의 코드가 우리가 예상하고 원하는 요구사항에 맞는지 확인할 수 있어야 한다.
  • API 스펙, Query, 메서드, 특정한 기능, 성능, UI 등이 어떻게 돼야 하는지 이러한 정의에 따라서 다양한 테스트 프레임워크나 라이브러리를 사용할 수 있다.
  • 이렇게 특정한 상황에 우리가 원하는 데로, 예상한 데로 동작하는 것을 검증하는 테스트 코드를 작성해두었다면 이 테스트 코드를 수행해서 모든 테스트가 성공하는지 확인해야 한다.
  • 만약 테스트가 실패하게 된다면 우리 코드가 어떤 부분이 잘못되었는지 확인하고 수정해야 한다.
  • 테스트가 다시 통과할 때까지 이 부분(pass)을 계속 반복해 줘야 한다.
  • 여기서 테스트의 포인트는 우리가 예상하는 요구사항에 맞게 우리 코드가 동작하는지 검증하는 것이다.
  • 많은 개발자들과 기업들이 TDD 방법론을 중요시하는 곳이 굉장히 많은 것을 볼 수 있다.
  • 그렇다면 TDD란 과연 무엇일까?


TDD(Test-Driven Development)란?

TDD(Test Driven Development)란?

  • Test-Driven Development의 약자이며, 테스트 주도 개발이라 한다.
  • 조금 풀어서 얘기하면 개발하기 전에 즉, 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 방식. 이렇게 개발하는 방식을 TDD라고 한다.
  • TDD는 특정한 기술 프레임워크나 라이브러리를 말하는 것이 아니라 우리가 어떻게 개발해 나갈 것인가를 정의하는 개발 방식, 개발 방법론 중에 하나이다.


TDD전 기존 개발 프로세스

TDD전 기존 개발 프로세스

  • TDD를 적용하기 전 개발 프로세스는 설계 및 디자인 -> 코드 개발 -> 해당 코드를 테스트 실행하게 된다.
  • 테스트를 진행 후 버그나 또는 변경사항이 발견된다거나 하게되면 다시 코드를 수정한다거나, 수정된 설계를 통해 다시 개발 코드를 수정하게 된다. 좀더 세분화해서 보자면..
  1. 코드를 작성하고
  2. 프로그램(Tomcat)을 실행한 뒤
  3. Postman과 같은 API 테스트 도구로 HTTP 요청을 하고
  4. 요청 결과를 System.out.println() 또는 log.debug()로 눈으로 검증하게 된다.
  5. 결과가 다르다면 다시 프로그램(Tomcat)을 중지하고 코드를 수정하게 된다.
  • 만약 수정할 코드들이 있다면 2 ~ 5번의 작업을 반복적으로 계속 수행해야 한다.
  • 또한 테스트를 실행하려면 프로그램(Tomcat)을 켜는데 시간도 상당히 소모되게 된다.


TDD Process

TDD Process

  1. 코드를 작성하기 전에 특정한 기능에 한에서, 기능도 조금 더 세분화해서 딱 하나의 케이스에 대해서 테스트 코드를 먼저 작성한다.
  2. 그리고 테스트를 실행하는데 당연히 실패하게 된다. 왜냐하면 기능을 구현하지 않았기 때문이다.
  3. 그래서 이 실패한 테스트가 성공할 정도의 조금의 양만, 딱 그만큼의 기능만 하는 코드를 작성해서 다시 테스트를 진행한다.
  4. 작성한 테스트를 성공하게 만든다.
  • 이렇게 하나의 테스트가 완성이 되면 이제 그다음 기능으로 넘어가서, 그 기능에 해당하는 테스트를 작성하고, 테스트를 수행해서 실패하면 이 실패한 코드가 성공할 수 있을 만큼의 코드만 작성해서 다시 테스트를 수행해서 성공하면 다시 그다음의 테스트를 진행한다.
  • 이렇게 테스트 코드를 조금 작성하고, 기능을 조금 구현하고 다시 테스트 코드를 조금 작성하고, 기능을 조금 구현하고 이런 식으로 개발해 나가는 것을 TDD라고 한다.
  • 이렇게 TDD 방법을 이용해서 모든 기능이 다 구현이 완료되었다면 그동안 작성해왔던 테스트 코드들이 성공적으로 통과되어야 한다.
  • 여기까지는 기능을 구현하는데 만 조금 더 집중해서 빠르게 코드를 작성했다면…


TDD(Test-Driven Development) Refactoring

TDD(Test Driven Development)

  • 이제 작성해둔 테스트 코드들을 기반으로 해서 조금 더 자신감 있게 코드에 퀄리티를 향상하고, 아키텍처를 개선하고, 리팩토링을 해나갈 수 있다.
  • 이렇게 실패하는 테스트 코드를 먼저 작성하고, 그에 해당하는 기능을 구현해나가는 방식 이것이 TDD인데…


오히려 코드량이 늘어나고 처리할 작업들이 많아지는데 왜 TDD를 지향해야 할까?

오히려 코드량이 늘어나고 처리할 작업들이 많아지는데 왜 TDD를 지향해야 할까?

  • 그렇다면 오히려 코드량이 늘어나고 처리해야할 작업들이 더 많아질텐데 왜 많은 사람들이 TDD… TDD… 하는 것일까?


TDD의 장점

TDD의 장점

  • 작성하고자 하는 모든 요구사항에 대한 철저한 분석명확한 이해가 필요하기 때문이다.
  • 명확한 요구 사항을 기반으로 해서 설계자의 관점에서 코드를 작성해 나갈 수 있기 때문이다.
  • 그래서 TDD를 이용하면 우리가 원하는 모든 요구 사항(목표)에 대해서 점검할 수 있다.
  • 또한, 사용자 입장에서 코드를 작성할 수 있다.
  • 이를 기반으로 테스트 코드에서 이런 식으로 우리 코드를 사용하면 되겠구나.. 라고 생각하게 되는데 조금 더 개발자스럽게 얘기해 보자면..
  • 구현보다는 인터페이스에 조금 더 집중해서 코드를 작성해 나갈 수 있다. =>구현 < 인터페이스 -> 코드의 퀄리티 향상
  • 이렇게 작성하면 당연히 코드의 퀄리티가 향상이 되고, 시스템 전반적인 설계를 향상할 수 있다.
  • 그리고 실패한 테스트 -> 기능구현, 실패한 테스트 -> 기능구현 이렇게 지속적으로 개발을 게임하듯이 해나갈 수 있기 때문에 개발 집중력도 향상할 수 있다.

결론

  • 무조건 TDD가 옳은 건 아니다. 하지만 개발에 있어 장점이 굉장히 많다.
  • 위 내용은 TDD에 관해 주로 장점을 설명하였다. 하지만 아래는 무조건 TDD를 사용하자! 가 아닌 적절하게, 꼭 필요한 곳에서 TDD를 사용해야 한다는 내용이다.
  • 아래는 포프TV - 효율적인 테스트 코드 작성법을 잘 요약한 설명이니 위 내용과의 차이점을 느끼고 생각해 보는 계기가 되었으면 한다.

효율적인 테스트 코드 작성법 - 요약

  • 소프트웨어 개발, 테스팅 또한 경제적인 활동이다. 자원(시간, 인력)을 적게 투입하여 최대한의 효용을 뽑아내어야 한다.
  • 코드에 따라 유닛 테스트는 필요할 때도 있고 필요하지 않을 때도 있다. 유닛 테스트가 필요한 경우는 다음과 같다.
    1. 알고리즘이 매우 복잡하지만 수학적으로 잘 정의된 경우, 구현 상의 명백한 버그를 없애기 위해 필요하다.
    2. 제품이 실제로 사용되고 발전하면서 자꾸 변하거나 가정이 틀리는 부분의 버그를 없애기 위해 필요하다.
  • 1에서는 TDD가 어느 정도 유용할 수 있으나 2에서는 쓸모가 없다. 코드의 어떤 부분이 변경될지 예측하는 것은 어렵기 때문이다.
  • 1은 애초에 안 변하고, TDD 방식으로 모든 코드에 대해 테스트를 짤 경우, 특히 2에서 코드를 변경해야 하는데 테스트가 발목을 잡는다.
  • 그러므로 (포프는) 제품 코드 전에 테스트 코드를 짜자는 TDD 방식을 쓰지 않는다.
  • 일단 코드를 그냥 짜고, 실제로 버그가 일어나고 가정이 틀리는 시점에서 그에 대한 테스트 코드를 작성한다

Reference