일기장
Published 2023. 9. 26. 01:49
TDD 웹개발

소프트웨어 개발을 할 때, 신규 기능을 추가하거나 코드를 변경하는 과정에서 오류를 발생시키는 것을 두려워하는 개발자들이 많습니다. TDD, 즉 테스트 주도 개발은 이러한 두려움을 해결해주는 도구이자 철학 중 하나입니다. 이 글에서는 TDD가 무엇인지, 그리고 어떻게 TDD를 사용해야할 지 알아보겠습니다!


 

TDD란 무엇일까

TDD는 소프트웨어 개발 방법론 중 하나로, 테스트를 먼저 작성한 다음 그 테스트가 통과되도록 코드를 작성하는 방법입니다. 즉, TDD는 매우 짧은 개발 사이클을 반복하는 소프트웨어 개발 프로세스입니다.

TDD의 기본적인 원리는 '빨간색 - 초록색 - 리팩토링' 순서로 진행됩니다.

 

  1. 빨간색은 작은 테스트를 작성하는 것입니다. 설령 컴파일에도 실패할지라도 구색만 갖춘 테스트를 먼저 작성합니다. 
  2. 초록색은 앞서 만든 빨간색 테스트를 통과하게끔 만드는 과정입니다. 이 과정에서 최소한의 코드를 작성하는데 이를 위해서는 하드코딩과 같은 어떠한 죄악도 저지를 수 있습니다.
  3. 리팩토링은 앞서 테스트를 통과시키면서 생겨난 모든 중복들을 제거하는 과정입니다. 말 그대로 리팩토링인만큼 인풋값에 따른 아웃풋이 달라져서는 안됩니다.

 

더보기

사람들은 TDD가 단순히 테스트 코드를 작성하면 끝이라고 생각하지만 사실 TDD는 'TFD(테스트 우선 개발) + 리팩토링'이다. 사실 TDD를 위해서는 요구사항을 분석하고 간략한 도메인을 설계하는 과정이 선행되어야 한다. 그래야 어떠한 테스트 코드를 작성해야할지 알 수 있기 때문이다. TDD는 최대한 단순하고 의존성이 떨어지는 부분부터 작성해나가야한다.


 

TDD 예시

1. 실패하는 테스트 케이스 작성

먼저, 덧셈 기능에 대한 테스트 케이스를 작성하겠습니다.

def test_add():
    calculator = Calculator()
    result = calculator.add(1, 2)
    assert result == 3

 

당연하지만 계산기 클래스는 정의되지 않았으므로 예외가 발생할 것입니다.

 

 

2. 테스트 케이스를 통과시키는 최소한의 코드 작성

이제 위 테스트 케이스를 통과시키기 위해 필요한 최소한의 코드를 작성합니다.

class Calculator:
    def add(self, a, b):
        return 3

 

이렇게 코드를 작성하면 `test_add` 테스트 케이스는 통과될 것입니다.

 

사실 이렇게 하드 코딩을 해놓으면 안되는 것 아닌가라는 생각이 들 수 있지만, 테스트 케이스를 통과시킨다는 관점에서 전혀 문제가 되지 않고 마찬가지로 따로 리팩토링할 것이 없는 완성된 코드입니다.

 

하지만 또 다른 테스트 케이스를 추가하면 어떻게 될까요?

def test_add2():
    calculator = Calculator()
    result = calculator.add(2, 3)
    assert result == 5

당연히 위의 테스트는 실패할 것입니다. 그렇기에 저희는 위의 두 가지 테스트를 모두 통과 시키도록 코드를 수정할 수 있습니다.

class Calculator:
    def add(self, a, b):
        return a+b

 

제가 감명깊게 들었던 강사님의 말씀이 있습니다. TDD는 코드를 작성함에 있어서 발생하는 불안감을 줄이는 일종의 도구이자 철학이라는 것인데요, 그런만큼 테스트 코드는 내가 혹은 팀의 불안이 해소될 때까지 작성해주면 됩니다.

 

3. 코드의 품질을 향상시키기 위한 리팩토링 과정 진행

테스트 코드도 유지 관리의 대상이다.

 

현재의 코드에서는 크게 리팩토링할 부분이 없어 보이시나요? 하지만 TDD를 수행함에 있어서 한 가지 유의할 점이 있는데 그것은 테스트 코드도 유지 관리의 대상이라는 점입니다.

 

두 가지의 테스트는 중복이 보입니다. 이를 없애주는 편이 좋을 것 같습니다.

import pytest
from your_calculator_module import Calculator

@pytest.mark.parametrize("input_a, input_b, expected", [
    (1, 2, 3),
    (2, 3, 5),
])
def test_add(input_a, input_b, expected):
    calculator = Calculator()
    result = calculator.add(input_a, input_b)
    assert result == expected

 

또한, 만약 Calculator클래스에 의미모를 숫자들이 존재할 경우 이는 상수처리 해주는 편이 좋습니다. 코드를 처음보는 사람들이 하나의 파일만 보더라도 어떠한 내용인지 파악할 수 있도록 하기 위해서입니다.

 


TDD가 개발에 대한 두려움을 어떻게 덜어주는가?

  1. 안정적인 코드 기반
    • TDD를 통해 작성된 코드는 요구사항에 맞게 잘 동작함을 테스트를 통해 보장받을 수 있습니다. 이로 인해 새로운 기능 추가나 리팩토링 시, 기존 기능이 올바르게 동작하는지 확인하기 쉽습니다.
  2. 반복적인 피드백
    • 테스트를 통과하면서 코드를 작성하는 과정에서 개발자는 지속적으로 빠른 피드백을 얻을 수 있습니다. 이는 코드의 방향성을 잡아주고 잘못된 구현을 빠르게 수정할 수 있도록 합니다.
  3. 문서의 역할
    • 테스트 코드를 작성함으로써 팀원들과 더 커뮤니케이션하기 쉬워집니다. 테스트 코드 자체가 어떻게 동작하는 지 명세서의 역할을 하기도 하고, 무엇보다 개발자가 빠른 피드백을 통해 팀원들과 커뮤니케이션할 자신감을 얻을 수 있습니다.

 

profile

일기장

@공군급양

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