IMCAT.DEV
로그인 가입
Ruby 중급 테스트

Ruby 테스트 주도 개발 (TDD)

Ruby 테스트 주도 개발 (TDD) — 중급

테스트 주도 개발 (TDD)

1. 도입 (왜 배워야 하는가)

테스트 주도 개발(TDD)은 소프트웨어 개발 과정에서 코드 작성 전에 테스트 케이스를 먼저 작성하는 개발 방식입니다. 이 접근 방식은 코드의 품질을 높이고, 버그를 사전에 예방할 수 있는 강력한 방법입니다. TDD를 배우는 것은 실무에서 매우 중요한데, 이는 코드의 유지보수성을 높이고, 팀원 간의 협업을 원활하게 하는 데 큰 도움을 줍니다.

TDD를 도입하지 않으면, 코드가 예상치 못한 방법으로 작동하거나, 시간이 지남에 따라 복잡해져서 유지보수가 어려워질 수 있습니다. 특히, 팀 프로젝트에서는 각자의 코드가 다른 개발자와 충돌하는 일이 잦아지므로, TDD를 통해 이러한 문제를 사전에 방지할 수 있습니다.

2. 핵심 개념 설명

2.1 TDD의 원칙

TDD는 'Red-Green-Refactor'라는 세 가지 단계로 나뉩니다.

  • Red: 실패하는 테스트를 작성하여 기능이 없음을 확인합니다.
  • Green: 테스트를 통과하는 최소한의 코드를 작성합니다.
  • Refactor: 코드를 리팩토링하여 가독성을 높이고 중복을 제거합니다.
  • 비유

    TDD는 요리를 할 때 레시피를 먼저 작성하고, 그에 맞춰 재료를 준비하는 것과 비슷합니다. 레시피(테스트)를 먼저 작성하면, 필요한 재료(코드)가 명확해지고, 요리 과정에서 실수를 줄일 수 있습니다.

    2.2 관련 용어 정리

    용어설명
    테스트 케이스특정 기능이 올바르게 작동하는지 검증하는 코드
    리팩토링코드의 구조를 개선하되 기능은 변경하지 않음
    단위 테스트개별 모듈이나 함수의 기능을 검증하는 테스트

    3. 기본 코드 예제

    TDD를 활용하여 간단한 덧셈 기능을 구현하는 예제를 살펴보겠습니다.

    # 1단계: 실패하는 테스트 작성
    def test_addition
      raise "테스트 실패: #{add(2, 3)}는 5가 아닙니다." unless add(2, 3) == 5
    end
    
    # 2단계: 최소한의 코드 작성
    def add(a, b)
      a + b
    end
    
    # 3단계: 테스트 실행
    test_addition

    실행 결과

    테스트 실패: 5는 5가 아닙니다.

    코드 한 줄씩 동작 설명

    1. test_addition 메서드를 정의합니다. 이 메서드는 덧셈 기능이 올바르게 작동하는지 확인합니다.
    2. raise 구문을 사용하여 조건이 맞지 않으면 오류를 발생시킵니다.
    3. add 메서드를 정의하고, 두 수를 더한 값을 반환합니다.
    4. test_addition 메서드를 호출하여 테스트를 실행합니다.
    5. 4. 실전 활용 예제

      예제 1: 쇼핑몰 장바구니 기능

      쇼핑몰에서 장바구니에 상품을 추가하는 기능을 TDD로 구현할 수 있습니다.

      # 실패하는 테스트
      def test_add_item
        cart = ShoppingCart.new
        cart.add_item("사과", 2)
        raise "테스트 실패: #{cart.items}는 ['사과', 2]가 아닙니다." unless cart.items == [["사과", 2]]
      end
      
      # 최소한의 코드
      class ShoppingCart
        attr_reader :items
      
        def initialize
          @items = []
        end
      
        def add_item(name, quantity)
          @items << [name, quantity]
        end
      end
      
      # 테스트 실행
      test_add_item

      예제 2: 사용자 인증

      사용자 인증 기능을 위한 테스트를 작성할 수 있습니다.

      # 실패하는 테스트
      def test_authenticate_user
        user = User.new("[email protected]", "password")
        raise "테스트 실패: #{user.authenticate("wrong_password")}는 false가 아닙니다." unless user.authenticate("wrong_password")  false
      end
      
      # 최소한의 코드
      class User
        attr_reader :email, :password
      
        def initialize(email, password)
          @email = email
          @password = password
        end
      
        def authenticate(input_password)
          input_password  @password
        end
      end
      
      # 테스트 실행
      test_authenticate_user

      5. 흔한 실수와 주의사항

      실수 1: 테스트를 먼저 작성하지 않기

    6. 잘못된 코드: 기능 구현 후 테스트 작성.
    7. 올바른 코드: 항상 테스트를 먼저 작성하여 실패를 확인.
    8. 실수 2: 리팩토링하지 않기

    9. 잘못된 코드: 코드 작성 후 리팩토링을 건너뛰는 것.
    10. 올바른 코드: 항상 리팩토링하여 가독성 높은 코드를 유지.
    11. 6. 정리

    12. TDD는 코드 품질을 높이고 유지보수를 용이하게 합니다.
    13. 'Red-Green-Refactor' 원칙을 따릅니다.
    14. 테스트 케이스를 먼저 작성하고, 그에 맞춰 코드를 구현합니다.
    15. 리팩토링을 통해 코드를 개선합니다.
    16. 다음에 학습하면 좋은 주제

    17. 단위 테스트와 통합 테스트의 차이
    18. Minitest 또는 RSpec 사용법
    19. CI/CD 도구와 TDD의 통합

TDD를 통해 더 나은 개발자로 성장하기 위한 체계적인 접근을 시작해보세요!