TDD와 BDD: 주요 차이점, 두 가지 방식으로 구축된 하나의 기능 및 각 사용 시기

  1. 홈
  2. 블로그
  3. 테스트 자동화

테스트 자동화

TDD와 BDD: 주요 차이점, 두 가지 방식으로 구축된 기능 및 각 사용 시기

TDD는 개발자가 올바른 코드를 설계하는 데 도움이 됩니다. BDD는 전체 팀이 소프트웨어가 수행해야 하는 작업에 동의하는 데 도움이 됩니다. 각 접근 방식으로 구축된 동일한 할인 기능을 확인하고 두 가지 접근 방식이 어떻게 함께 작동하는지 알아보세요.

읽는 시간 9분
TDD와 BDD: 주요 차이점, 두 가지 방식으로 구축된 하나의 기능 및 각 사용 시기

핵심 요약

  • TDD는 먼저 실패한 테스트를 작성한 다음 통과할 만큼의 코드만 작성하고 정리하는 것을 의미합니다.
  • BDD는 일반적으로 Give, When, Then과 같은 공유 언어의 동작을 설명합니다.
  • TDD는 주로 코드 디자인을 안내합니다. BDD는 주로 공유된 이해를 구축합니다.
  • 그들은 경쟁자가 아니며 많은 팀이 기능을 위해 BDD를 사용하고 아래 세부 사항을 위해 TDD를 사용합니다.

TDD 대 BDD 논쟁은 종종 한쪽을 선택하는 것으로 구성됩니다. 실제로 그들은 다른 질문에 대답합니다. 테스트 중심 개발은 코드가 개발자가 의도한 대로 작동하는지 여부를 묻는 반면, 행동 중심 개발은 소프트웨어가 수행해야 하는 작업에 대해 팀이 동의하는지 여부를 묻습니다.

차이점을 구체적으로 만들기 위해 각 접근 방식에 대해 하나의 작은 할인 기능을 구축합니다. 표준 라이브러리를 사용하여 Python 3.13에서 코드를 실행했으며 아래 결과는 해당 실행에서 나온 것입니다. BDD 부분은 메커니즘을 보여주기 위해 우리 자신의 작은 러너를 사용하므로 실제 프로젝트에서는 Cucumber와 같은 도구를 사용하거나 대신 작동합니다.

짧은 대답

테스트 중심 개발(TDD)은 코딩 관행입니다. 작은 실패 테스트를 작성하고 가장 간단한 코드로 테스트를 통과시킨 다음 디자인을 개선합니다. 테스트는 주로 개발자가 코드로 작성합니다. Kent Beck은 이 관행을 대중화했습니다.

행동 중심 개발(BDD)은 TDD에서 발전한 협업 관행이며 Dan North가 이 용어를 도입했습니다. 개발자, 테스터 및 비즈니스 담당자는 시스템이 어떻게 작동해야 하는지에 대한 예에 동의하고 일반 언어로 작성되며 해당 예는 자동화될 수 있습니다.

TDD와 BDD를 나란히 놓고

측면 TDD BDD
주요 초점 정확하고 잘 설계된 코드 행동에 대한 공유된 이해
에 작성 프로그래밍 언어 Gherkin과 같은 일반 언어
작성자: 개발자 비즈니스, QA, 개발자가 함께
읽을 수 있는 사람 개발자 팀의 모든 사람
일반적인 수준 단위 기능 또는 승인
출발점 실패한 테스트 예시를 통한 대화
주기 빨간색, 녹색, 리팩터링 발견, 공식화, 자동화
일반적인 도구 pytest, JUnit, Jest 오이, 행동, SpecFlow, Reqnroll

특징

우리가 구현할 비즈니스 규칙은 다음과 같습니다. 1000개 이상 주문 시 10% 할인을 받습니다. 회원은 해당 주문에 대해 추가로 5% 할인을 받을 수 있습니다.

분명하게 들릴 수도 있지만 이미 모호합니다. 500불 구매 회원은 5% 할인을 받을 수 있나요? 문장에는 “그 명령”이라고 적혀 있으므로 그렇지 않다고 가정합니다. BDD가 조기에 제기하도록 설계된 질문이 바로 이것이기 때문입니다.

TDD로 빌드하기

TDD는 빨간색, 녹색, 리팩터링이라는 짧은 루프를 따릅니다.

단계 당신이 하는 일
빨간색 아직 존재하지 않는 동작에 대한 테스트를 작성하고 실패하는 것을 지켜보세요.
녹색 이를 통과시키는 가장 간단한 코드를 작성하세요.
리팩터링 코드를 개선하여 테스트를 친환경적으로 유지

다음은 각 규칙에 대해 하나씩 테스트하는 것입니다.

class DiscountTests(unittest.TestCase):
    def test_no_discount_below_1000(self):
        self.assertEqual(discount(999, False), 0)

    def test_ten_percent_from_1000(self):
        self.assertEqual(discount(1000, False), 100)

    def test_member_gets_extra_five_percent(self):
        self.assertEqual(discount(1000, True), 150)

그런 다음 세 단계로 코드를 작성하고 각 단계마다 테스트를 실행했습니다. 엄격한 TDD 세션은 한 번에 하나의 테스트를 추가하며 이는 동일한 진행을 보여줍니다.

1단계: 가장 간단한 것

def discount(total, is_member):
    return 0

# 3 tests, 2 failed
#   test_member_gets_extra_five_percent
#   test_ten_percent_from_1000

0을 반환하는 것은 어리석은 것처럼 보이지만 테스트가 실제로 실패할 수 있음을 증명하며 통과한 테스트 중 하나는 “할인 없음” 규칙입니다.

2단계: 임계값 추가

def discount(total, is_member):
    if total >= 1000:
        return total * 0.1
    return 0

# 3 tests, 1 failed
#   test_member_gets_extra_five_percent

3단계: 구성원 추가 및 정리

def discount(total, is_member):
    rate = 0.1 if total >= 1000 else 0
    if is_member:
        rate += 0.05
    return round(total * rate, 2)

# 3 tests, 0 failed

세 가지 모두 통과합니다. 하지만 이 버전을 자세히 읽어보세요. 이는 500을 지출하는 회원에게 5% 할인을 제공하는데, 이는 규칙이 의미하는 바가 아닙니다. 해당 사례를 다루는 테스트가 없었기 때문에 아무 것도 표시되지 않았습니다. TDD는 테스트하려고 생각한 동작만 보호합니다. 이는 실제 제한 사항이며 예제에 대한 대화가 그토록 중요한 이유입니다.

주기가 중요한 이유

  • 빨간색은 테스트가 작동한다는 것을 증명합니다. 한 번도 실패한 테스트는 아무것도 테스트하지 않을 수 있습니다.
  • 녹색은 집중을 유지합니다. 필요한 코드만 작성하므로 과도한 엔지니어링을 방지하는 데 도움이 됩니다.
  • 리팩터링을 통해 품질을 높게 유지합니다. 테스트를 통해 디자인을 안전하게 변경할 수 있다는 자신감을 얻을 수 있습니다.
  • 디자인에 영향을 줍니다. 테스트하기 어려운 코드는 너무 긴밀하게 결합되어 있는 경우가 많으며 즉시 알아챌 수 있습니다.

우리의 pytest 튜토리얼은 이와 같은 테스트를 작성하는 더 편리한 방법을 보여주고, 경계 값 분석은 우리가 999와 1000을 값으로 선택한 이유를 설명합니다.

BDD로 빌드하기

BDD는 도구가 아닌 대화로 시작됩니다. 종종 이는 제품 담당자, 개발자 및 테스터가 구체적인 예를 논의하는 세 친구로 알려진 짧은 회의입니다.

Tester:  What about a member spending 500?
Product: Good question. No discount. It has to reach 1000 first.
Dev:     And exactly 1000 counts?
Product: Yes, 1000 or more.

그 교환 하나가 우리 TDD 코드의 문제를 포착했을 것입니다. 그런 다음 Gherkin이라는 구조화된 형식으로 예제를 기록합니다.

Feature: Order discounts

  Scenario: Member reaches the discount threshold
    Given a member with a cart worth 1000
    When they view the amount to pay
    Then the amount to pay is 850

  Scenario: Member below the threshold gets no discount
    Given a member with a cart worth 500
    When they view the amount to pay
    Then the amount to pay is 500
키워드 목적
주어진 시작 상황
언제 행동이나 사건
그런 다음 예상되는 결과

팀원 누구나 그것을 읽고 “예, 맞습니다” 또는 “아니요, 그건 틀렸습니다”라고 말할 수 있습니다. 자동화하지 않더라도 시나리오는 이미 유용한 작업을 수행했습니다.

단계를 코드에 연결하기

도구는 각 일반 언어 행을 단계 정의라고 하는 함수에 연결합니다. 아이디어를 보여주기 위해 우리는 작은 버전을 직접 작성하고 첫 번째 시나리오를 실행했습니다.

@step("a member with a cart worth 1000")
def given(ctx):
    ctx["cart"] = Cart(is_member=True)
    ctx["cart"].add(1000)

@step("they view the amount to pay")
def when(ctx):
    ctx["amount"] = ctx["cart"].payable()

@step("the amount to pay is 850")
def then(ctx):
    assert ctx["amount"] == 850

# ok Given a member with a cart worth 1000
# ok When they view the amount to pay
# ok Then the amount to pay is 850

실제 도구는 매개변수를 추가하므로 단일 단계가 “1000” 및 “500”과 보고 기능을 모두 일치시킬 수 있습니다. 그 결과는 살아있는 문서입니다. 즉, 사실이 아닌 경우 크게 실패하는 시스템에 대한 간단한 설명입니다.

팁: BDD의 가치는 대화에 있습니다. 코드가 완료된 후 한 사람이 Gherkin을 혼자 작성하는 팀은 도구 비용만 얻고 이점은 거의 없습니다.

좋은 시나리오 쓰기

약함 더 나은
ID가 "btn-77"인 버튼을 클릭하면 쿠폰을 적용하면
그럼 결과는 맞아요 그러면 지불할 금액은 850 입니다
하나의 시나리오에서 20단계 시나리오당 하나의 동작
화면에 대해 설명합니다 비즈니스 의도를 설명합니다.

클릭 수와 필드 ID를 설명하는 시나리오는 재설계할 때마다 중단되며 비즈니스 독자는 해당 시나리오 읽기를 중단합니다. 단계 코드에 사용자 인터페이스 세부정보를 유지합니다. 이러한 시나리오는 테스트 사례와 테스트 시나리오의 예제와 가까운 사촌이며 사용자 승인 테스트에도 자주 사용됩니다.

둘 다 함께 사용

두 가지 방법은 자연스럽게 “외부-내부” 작업 흐름에 적합합니다.

  1. 팀은 행동에 동의하고 BDD 시나리오를 작성합니다. 아직 아무것도 존재하지 않기 때문에 실패합니다.
  2. 개발자는 TDD를 사용하여 필요한 작은 단위를 구축합니다.
  3. 단위 테스트가 통과되고 결국 시나리오도 통과됩니다.
  4. 모든 것이 CI/CD 파이프라인에서 실행됩니다.

각각을 올바른 수준으로 유지하십시오. 중요한 동작에 대한 몇 가지 시나리오와 세부 사항에 대한 빠른 단위 테스트가 많이 있어야 합니다. 단위 테스트와 통합 테스트에 대한 가이드에서는 균형을 다룹니다.

도구

언어 TDD(단위 테스트) BDD
파이썬 파이테스트, 유닛테스트 행동하다, pytest-bdd
자바스크립트 농담, 비테스트 Cucumber.js
자바 JUnit, 테스트NG 오이-JVM
.NET x유닛, NUnit 요청, SpecFlow

각각을 사용하는 경우

TDD는 다음과 같은 경우에 적합합니다.

  • 가격 책정, 구문 분석 또는 권한과 같은 복잡한 논리를 작성하고 있습니다.
  • 실패한 테스트를 통해 먼저 버그를 재현할 수 있으므로 버그를 수정하는 것입니다.
  • 당신은 자주 변경되는 코드를 작업하고 있습니다.

BDD는 다음과 같은 경우에 적합합니다.

  • 비즈니스 규칙은 복잡하고 오해로 인해 비용이 많이 듭니다.
  • 기술적인 지식이 없는 사람들도 실제로 시나리오를 읽고 토론할 것입니다.
  • 여러 팀에서는 사물의 작동 방식에 대한 공유 정의가 필요합니다.

다음과 같은 경우에는 과잉일 수 있습니다. 일회용 프로토타입을 작성하거나 불분명한 기술 아이디어를 탐구하는 경우입니다. 많은 개발자가 먼저 급증한 다음 테스트를 통해 다시 작성합니다. 엔지니어링 외부의 누구도 시나리오를 살펴보지 않는다면 BDD 도구는 잘못된 투자이기도 합니다. 이 경우 좋은 이름을 사용한 일반 테스트가 더 간단합니다.

일반적인 실수

  • BDD를 테스트 도구로 사용합니다. 공동 작업이 없는 오이는 테스트를 작성하는 장황한 방법일 뿐입니다.
  • TDD의 테스트 구현. 비공개 세부정보와 연결된 테스트는 리팩토링할 때마다 중단됩니다.
  • 리팩터링 단계를 건너뜁니다. 지저분한 코드 위에서 테스트를 통과하게 됩니다.
  • 코드 다음에 테스트를 작성하고 이를 TDD라고 부릅니다. 이는 여전히 유용하지만 디자인 피드백을 잃게 됩니다.
  • UI 시나리오를 너무 많이 작성합니다. 속도가 느리고 불안정해집니다. 불안정한 테스트를 참조하세요.
  • 적용 범위를 쫓는 것. 우리의 예에서 볼 수 있듯이 좋은 적용 범위는 여전히 아무도 고려하지 않은 행동을 놓치고 있습니다.

마무리

TDD는 올바른 것을 구축하는 데 도움이 되고 BDD는 올바른 것을 구축하는 데 도움이 됩니다. 우리의 할인 예는 양면을 보여주었습니다. 코드는 모든 테스트를 통과했지만 간단한 대화에서는 잘못된 가정이 드러났습니다. 다음 작은 기능에 사용해 보세요. 코드를 작성하기 전에 동료와 함께 세 가지 구체적인 예를 작성한 다음 한 번에 하나의 실패한 테스트를 빌드하세요.

자주 묻는 질문

TDD와 BDD의 주요 차이점은 무엇입니까?

TDD는 개발자가 구현 전에 실패한 코드 테스트를 작성하는 데 중점을 둡니다. BDD는 일반 언어 예제를 사용하여 전체 팀이 행동에 동의하는 데 중점을 둡니다.

TDD와 BDD를 함께 사용할 수 있나요?

예, 많은 팀이 그렇습니다. BDD 시나리오는 외부에서 기능을 정의하고 TDD는 그 아래에 있는 더 작은 코드 단위를 구동합니다.

BDD가 TDD보다 나은가요?

둘 다 서로 다른 문제를 해결하므로 전반적으로 더 나은 것은 아닙니다. BDD는 공유된 이해에 도움이 되고, TDD는 코드 설계와 빠른 피드백에 도움이 됩니다.

거킨이란 무엇입니까?

Gherkin은 Give, When, Then과 같은 키워드를 사용하여 시나리오를 작성하기 위한 구조화된 일반 언어 형식입니다. Cucumber와 같은 도구를 사용하여 실행할 수 있습니다.

TDD가 개발 속도를 늦추나요?

처음에는 특히 학습하는 동안 속도가 느려질 수 있습니다. 팀은 버그 감소와 안전한 변경을 통해 시간을 확보하는 경우가 많지만 그 효과는 프로젝트에 따라 다릅니다.

계속 학습하세요

Stack Quora와 작업

테스트, WordPress 또는 SEO에 도움이 필요하십니까?

우리는 팀이 더 나은 소프트웨어를 출시하고 사이트를 성장시킬 수 있도록 돕습니다. 현재 진행 중인 작업을 알려주시면 명확한 다음 단계를 제안해 드리겠습니다.

계속 읽으세요

추가 가이드 테스트, AI 및 최신 개발

이 기사가 마음에 드셨나요? 주제를 선택하고 최신 튜토리얼로 바로 이동하세요.

인공지능

AI 환각 설명: 언어 모델이 사물을 구성하는 이유와 이를 줄이는 방법

AI 환각은 그것이 무엇인지, 언어 모델이 환각을 생성하는 이유, 일반적인 유형, 접지 및 프롬프트를 통해 환각을 줄이는 방법, 그리고 우리가 실행한 간단한 점검에 대해 설명했습니다.

기사 읽기 →
DevOps

환경 변수 설명: .env 파일, 비밀 및 구성이 올바르게 완료되었습니다.

우리가 실행한 Python 예제를 통해 설명된 환경 변수: 읽기 및 설정, 모든 값이 문자열인 이유, .env 파일, 프로세스 상속, 비밀 및 유효성 검사.

기사 읽기 →
소프트웨어 개발

API 속도 제한 설명: 알고리즘, 헤더 및 429 오류 처리

우리가 실행한 시뮬레이션을 통해 설명된 API 속도 제한: 토큰 버킷, 고정 창, 슬라이딩 창, 429 응답, 속도 제한 헤더, 백오프를 사용한 재시도 및 테스트 제한.

기사 읽기 →
테스트 자동화

Python에서 조롱: unittest.mock, 패치 및 테스트를 거짓말로 만드는 실수

Unittest.mock을 사용하여 Python에서 모의, 테스트됨: 모의 및 return_value, 부작용, 이름이 사용되는 패치, 사양 및 자동 사양, 모의 날짜 및 일반적인 실수.

기사 읽기 →
소프트웨어 테스트

코드 커버리지 설명: 회선 커버리지와 분기 커버리지 및 100%의 실제 의미

실제 Coverage.py 실행을 통해 설명되는 코드 적용 범위: 라인, 분기 및 조건 적용 범위, 보고서 읽기, 100% 적용 범위가 여전히 버그를 놓칠 수 있는 이유 및 합리적인 대상.

기사 읽기 →
데이터베이스 및 SQL

SQL의 DELETE vs TRUNCATE vs DROP: 차이점, 롤백 및 사용 시기

테스트된 SQL을 통해 DELETE 대 TRUNCATE 대 DROP에 대해 설명합니다. 각각의 제거, 롤백, 트리거, ID 재설정, 속도 및 PostgreSQL, MySQL, SQL Server 및 SQLite의 차이점.

기사 읽기 →
데이터베이스 및 SQL

SQL 뷰 설명: 예제를 통해 함정 생성, 사용 및 방지

우리가 실행한 쿼리로 설명된 SQL 뷰: 뷰 생성, 실시간 결과, 열 숨기기, 성능, 업데이트 가능하고 구체화된 뷰, 손상된 종속성 및 모범 사례.

기사 읽기 →
소프트웨어 개발

TypeScript 인터페이스와 유형: 실제 차이점, 컴파일러로 테스트

TypeScript 인터페이스 대 유형, 실제 컴파일러로 확인: 둘 다 할 수 있는 것, 하나만 할 수 있는 것, 선언 병합, 확장 대 교차점 및 따라야 할 간단한 규칙.

기사 읽기 →
소프트웨어 개발

Python *args 및 **kwargs 설명: 명확한 예가 포함된 유연한 함수

Python *args 및 **kwargs는 우리가 실행한 코드(패킹 및 언패킹, 매개변수 순서, 키워드 전용 및 위치 전용 인수, 데코레이터 및 일반적인 오류)를 설명했습니다.

기사 읽기 →
소프트웨어 개발

Python Lambda 함수: 구문, 실제 사용 및 사용하지 말아야 할 경우

Python 람다 함수는 구문, 키를 사용한 정렬, 맵 및 필터, 클로저, 후기 바인딩 트랩, 일반 def가 더 나은 선택인 경우 등 우리가 실행한 코드로 설명되었습니다.

기사 읽기 →
인공지능

AI 에이전트란 ​​무엇입니까? 작동 방식, 간단한 에이전트 루프를 사용하여 실행할 수 있음

AI 에이전트란 무엇입니까? 우리가 실행한 작은 Python 루프, 실제 위험 및 간단한 챗봇이 더 나은 선택일 때 에이전트 루프, 도구, 메모리 및 가드레일에 대한 일반 가이드입니다.

기사 읽기 →
DevOps

모니터링과 관찰 가능성: 로그, 지표, 추적을 통한 실제 차이점

모니터링과 관찰 가능성 설명: 알려진 오류와 알려지지 않은 오류, 로그, 지표 및 추적, 결제 사건 안내, 골든 신호, OpenTelemetry 및 유용한 경고.

기사 읽기 →
DevOps

Docker 볼륨과 바인딩 마운트: 컨테이너 데이터를 올바른 방식으로 유지

Docker 볼륨과 바인드 마운트 설명: 컨테이너 데이터가 사라지는 이유, 명명된 볼륨, 바인드 마운트, tmpfs, Compose 예제, 백업, 권한 및 각 사용 시기.

기사 읽기 →
테스트 자동화

TDD와 BDD: 주요 차이점, 두 가지 방식으로 구축된 하나의 기능 및 각 사용 시기

TDD와 BDD는 두 가지 방식으로 구축된 하나의 할인 기능, 즉 우리가 실행한 코드를 사용한 적록 리팩토링, 주어진 시점 시나리오, 도구, 장단점 및 각 사용 시기를 설명합니다.

기사 읽기 →
소프트웨어 개발

Git merge vs rebase: 차이점, 예제, 언제 무엇을 쓸까

Git merge vs rebase를 실제 로그 출력, 비교표, rebase의 황금률, 안전한 팀 워크플로로 설명합니다.

기사 읽기 →
소프트웨어 개발

파이썬 리스트 컴프리헨션: 문법, 예제, 피해야 할 때

파이썬 리스트 컴프리헨션 설명: 문법, 필터링, if-else, 중첩 반복문, 실제 측정 시간, 그리고 일반 for 반복문이 더 나은 경우.

기사 읽기 →
데이터베이스 및 SQL

예제로 쉽게 배우는 SQL JOIN (Inner, Left, Right, Full)

샘플 테이블과 쿼리로 SQL JOIN을 단계별로 이해하세요. INNER, LEFT, RIGHT, FULL, CROSS, SELF와 흔한 실수, 성능 팁까지 정리했습니다.

기사 읽기 →