TDD 방법론을 하향식으로 적용 할 수 있습니까?


13

방법론 인 TDD가 다음과 같은 경우를 어떻게 처리하는지 잘 모르겠습니다. 파이썬에서 mergesort 알고리즘을 구현하고 싶다고 가정 해보십시오. 나는 글로 시작

assert mergesort([]) === []

테스트는 실패

NameError : 이름 'mergesort'가 정의되지 않았습니다

그런 다음 추가

def mergesort(a):
    return []

그리고 나의 시험은 통과한다. 다음으로 추가

assert mergesort[5] == 5

내 테스트는 실패

AssertionError

내가 통과하는

def mergesort(a):
    if not a:
        return []
    else:
        return a

다음으로 추가합니다

assert mergesort([10, 30, 20]) == [10, 20, 30]

그리고 지금이 패스를 만들려고 노력해야합니다. 나는 mergesort 알고리즘을 "알고"다음과 같이 작성한다

def mergesort(a):
    if not a:
        return []
    else:
        left, right = a[:len(a)//2], a[len(a)//2:]
        return merge(mergesort(left)), mergesort(right))

그리고 이것은 실패

NameError : 이름 '병합'이 정의되지 않았습니다

이제 질문이 있습니다. mergeTDD를 사용하여 실행을 시작하고 구현 을 시작하려면 어떻게 해야합니까? 내가이, 이루어지지 않은 "걸려"에 대한 테스트를 실패하지 않았을 수 있기 때문에 것 같다 mergesort, 까지 통과하지 것이다 merge완료! 이 테스트가 중단되면 TDD 반복을 구성하는 동안 "녹색"이 아니기 때문에 실제로 TDD를 수행 할 수 없습니다 merge.

다음 세 가지 추악한 시나리오에 갇혀있는 것처럼 보이며 (1) TDD 커뮤니티가 선호하는 방법 중 하나 또는 (2) 내가 놓친 또 다른 접근법이 무엇인지 알고 싶습니다. 나는 밥 삼촌 TDD 연습 몇 가지를 보았고 전에 이런 사례를 본 것을 기억하지 않습니다!

다음은 세 가지 경우입니다.

  1. 다른 테스트 스위트를 사용하여 다른 디렉토리에 병합을 구현하십시오.
  2. 헬퍼 기능을 개발할 때 친환경에 대해 걱정하지 말고 실제로 통과하려는 테스트를 수동으로 추적하십시오 .
  3. mergesort해당 통화 에서 라인을 주석 처리 (GASP!)하거나 삭제하십시오 merge. 그런 다음 merge일 을 마치고 다시 넣습니다.

이것들은 모두 나에게 어리석게 보입니다 (또는 내가 잘못보고 있습니까?). 누구든지 선호하는 접근법을 알고 있습니까?


2
TDD의 목표 중 하나는 소프트웨어 디자인 작성을 돕는 것입니다. 이 디자인 프로세스의 일부는 원하는 결과를 생성하는 데 필요한 것을 발견하는 것입니다. 의 경우 mergesort, 이미 잘 정의 된 알고리즘이므로이 발견 프로세스는 필요하지 않으며, 이미 디자인으로 알고있는 것을 일련의 단위 테스트에 맵핑하는 문제가됩니다. 아마도 최상위 레벨 테스트에서는 테스트중인 메소드가 정렬되지 않은 콜렉션을 승인하고 정렬 된 콜렉션을 리턴한다고 가정합니다.
Robert Harvey

1
이후의 단위 테스트는 점차 실제의 역학에 대해 더 깊이 파고들 것 mergesort입니다. 이를위한 "올바른"방법을 찾고 있다면 mergesort알고리즘을 일련의 단위 테스트에 매핑하는 것 외에 다른 방법은 없습니다 . 즉 그들은 mergesort실제로 하는 일을 반영해야한다 .
Robert Harvey

4
디자인은 단위 테스트만으로 성장하지 않습니다. mergesort빨강-녹색 리 팩터에서 설계가 자연스럽게 나타날 것으로 예상되는 경우 기존 지식을 기반으로 프로세스를 안내하지 않는 한 발생하지 않습니다 mergesort.
Robert Harvey


1
TDD merge에서 "리팩토링"단계에서만 발명해야합니다. merge테스트 통과를 위해 메소드를 도입 할 수있는 경우 mergesort먼저 merge메소드 없이 테스트를 통과하도록하십시오 . 그런 다음 merge메소드 를 도입하여 구현을 리팩토링하십시오 .
Fabio

답변:


13

다음은 옵션을 볼 수있는 다른 방법입니다. 그러나 우선, 나에게 강조한 Bob 아저씨 의 TDD 규칙

  1. 실패한 단위 테스트를 통과하지 않으면 프로덕션 코드를 작성할 수 없습니다.
  2. 실패하기에 충분한 단위 테스트를 더 이상 작성할 수 없습니다. 컴파일 실패는 실패입니다.
  3. 하나의 실패한 단위 테스트를 통과 하기에 충분한 양보다 더 많은 생산 코드 를 작성할 수 없습니다 .

따라서 규칙 번호 3을 읽는 한 가지 방법 merge은 테스트를 통과하는 함수가 필요 하므로 가장 기본적인 형식으로 만 구현할 수 있다는 것입니다.

또는 병합 작업을 인라인으로 작성하여 시작한 다음 테스트가 작동하도록 한 후 함수로 리팩토링합니다.

또 다른 해석은 mergesort를 작성하고 있다는 것입니다. merge작업 이 필요하다는 것을 알고 있습니다 (즉, "충분한"규칙이 축소하려고하는 YAGNI가 아닙니다). 따라서 병합 테스트를 시작한 다음 전체 정렬 테스트 만 진행해야합니다.


이것들은 정말 좋은 관찰입니다. 나는 이전에 인라인 및 팩토링에 대해 생각했지만 merge놀랍게도 지저분하고 (독립형뿐만 아니라 독립형으로도 유용합니다) 별도의 함수로 수행한다는 아이디어가 더 합리적이었습니다. 그러나 기본 형식으로 인라인으로 만든 다음 파란 모자 단계에서 요소를 분류하는 스타일은 실제로 옳고 매우 내가 원하는 것 같습니다.
Ray Toal

@RayToal-실제로 merge정렬을 수행하기 전에 작업 을 완전히 테스트하는 방법 과 별도 의 작업 테스트 방법에 의존 partition합니다. 주장 된 이점은 설계가 알려진 목표를 향해 서서히 작업하는 것에서 비롯된 것이라고 생각합니다. mergesort의 경우 목표가 일반적으로 정렬 되지 않는다고 생각합니다 ( 그러므로 거품 정렬로 끝날 것입니다). 기본 작업을 알고 있으므로 해당 작업을 향해 작업합니다. 정렬은 대부분 나중에 생각합니다.
kdgregory

1
네 번째 옵션이 있습니다. 패스 merge로 기능을 mergesort하고 행동을 조롱. 그런 다음 돌아가서 merge테스트를 먼저 구현하십시오 . 대리인은 굉장합니다.
RubberDuck

@RubberDuck 핵심 도메인의 핵심 부분을 모의하면 프로그램을 실행할 때 문제가 발생할 수 있으며, 조롱 및 병합 기능은 세부 사항이 다릅니다. 정렬 할 목록의 출처와 같은 외부 리소스를 사용하는 경우에는 이와 같은 방법을 사용해야합니다.
cllamach
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.