TDD : 내가 제대로하고 있니?


14

나는 새로운 프로그래머 (약 1 년 동안 만 배우고 있음)이고 더 나은 목표를 위해 최근에 TDD에 대해 배웠습니다. 나는 그것이 매우 도움이되는 것처럼 그것을 사용하는 습관에 들어가기를 원했습니다. 확인하고 올바르게 사용하고 있는지 확인하고 싶었습니다.

내가하고있는 것:

  1. 내가 필요한 새로운 방법을 생각하십시오.
  2. 해당 방법에 대한 테스트를 작성하십시오.
  3. 실패 테스트.
  4. 쓰기 방법.
  5. 합격 시험.
  6. 리팩터링 방법.
  7. 반복.

나는 내가 쓰는 모든 방법에 대해 이것을하고 있는데, 귀찮게해서는 안되는 것이 있습니까? 나중에 나는 이미 기존의 방법을 다른 방법이나 상황에서 테스트하는 방법을 생각합니다. 이 새로운 테스트를 생각해야합니까, 아니면 각 방법에 이미 자체 테스트가 있으므로 귀찮게하지 않아야합니까? 내 코드를 오버 테스트 할 수 있습니까?이 질문에 대한 주요 관심사라고 생각합니다.

편집하다

또한 이것은 내가 궁금했던 것입니다. GUI를 만드는 것과 같은 일을 할 때 그 상황에서 TDD가 필요합니까? 개인적으로, 나는 그것을 위해 어떻게 시험을 쓸 것인지 생각할 수 없습니다.


5
당신은 이미 모든 것을 테스트하고 있다고 말하는 노련한 전문가보다 훨씬 더 잘하고 있습니다.
yannis

당신이 설명하는 것은 TDD 의 정신 이 아닙니다 .

1
ATDD 또는 BDD를 살펴볼 수 있습니다.
dietbuddha

아마도 더 높은 곳에서 시작하십시오- 필요한 새로운 모듈 을 생각해보십시오 .

답변:


16

워크 플로로 설명하는 것은 TDD 의 정신 이 아닙니다 .

아마존에 대한 켄트 벡스 (Kent Becks) 책의 개요는 다음과 같이 말합니다.

테스트 중심 개발은 응용 프로그램 개발에 대한 두려움을 없애기위한 것입니다.어떤 두려움은 건강하지만 (종종 프로그래머에게 "주의해야한다"는 양심으로 여겨지지만) 저자는 두려움의 부산물에는 건설적인 비판을 흡수 할 수없는 잠정적, 심술쟁이 및 의사 소통이없는 프로그래머가 포함된다고 생각합니다. 프로그래밍 팀이 TDD를 구매하면 즉시 긍정적 인 결과를 보게됩니다. 그들은 자신의 직무와 관련된 두려움을 제거하고, 직면 한 어려운 도전에 대처할 수있는 능력을 갖추고 있습니다. TDD는 잠정적 인 특성을 제거하고, 프로그래머에게 의사 소통을 가르치며, 팀원들이 비판을 받도록 장려합니다. 그러나 저자조차도 심술이 개별적으로 해결되어야한다는 것을 인정합니다! 요컨대, TDD의 전제는 코드를 지속적으로 테스트하고 리팩토링해야한다는 것입니다.

실용 TDD

공식적인 자동화 테스트, 특히 모든 클래스의 모든 방법을 테스트하는 것은 안티 패턴만큼이나 나쁘지 않으며 아무 것도 테스트하지 않습니다. 가질 균형이 있습니다. 모든 setXXX/getXXX방법에 대해 단위 테스트를 작성하고 있습니까 ?

또한 테스트는 시간과 비용을 절약하는 데 도움이 될 수 있지만 개발하는 데 시간과 비용이 들며 코드이므로 유지 관리하는 데 시간과 비용이 든다는 것을 잊지 마십시오. 만약 그들이 유지 보수 부족으로 위축된다면 그들은 이익 이상의 책임이됩니다.

이와 같은 모든 것과 마찬가지로, 자신 외에는 누구도 정의 할 수없는 균형 이 있습니다. 어떤 교리이든 어느 쪽이든 더 정확할 것입니다.

좋은 척도는 비즈니스 로직에 중요하고 변화하는 요구 사항에 따라 자주 수정해야하는 코드입니다. 이러한 것들에는 자동화 된 공식 테스트가 필요하며 이는 큰 투자 수익입니다.

이런 식으로 작동하는 많은 전문 상점을 찾기 위해 매우 압박을 받게 될 것입니다. 단순한 연기 테스트를 수행 한 후에는 절대 변하지 않는 모든 실질적인 목적으로 돈을 테스트하는 데 돈을 쓰는 것이 사업 적으로 의미가 없습니다. .getXXX/.setXXX방법에 대한 공식적인 자동화 된 단위 테스트를 작성 하는 것이 완전한 시간 낭비의 주요 예입니다.

프로그램 테스트가 버그의 존재를 설득력있게 보여줄 수는 있지만, 그 부재를 보여줄 수는 없다고 지적 된 지 20 년이 지났습니다. 이 잘 알려진 발언을 솔직하게 인용 한 후, 소프트웨어 엔지니어는 요크의 연금술사처럼 계속해서 그의 크리 소 코믹스 정화를 개선 한 테스트 전략을 계속 수정합니다.

- Edsger W. Djikstra . (1988 년에 작성되었으므로 현재 4.5 년에 가깝습니다.)

답변 도 참조하십시오 .


1
그것은 내가 걱정했던 것을 거의 다룬다. 나는 나처럼 모든 방법을 테스트해서는 안된다고 생각했지만 확실하지 않았습니다. TDD에 대해 좀 더 읽어야 할 것 같습니다.
cgasser

@kevincline 대부분의 시간 setXXX/getXXX이 전혀 필요하지 않습니다 :)
Chip

1
사소한 getXXX를 기억하고 잘못 얻거나 getXXX에 게으른 로딩을 도입하여 잘못하면, 때때로 getter를 테스트하고 싶어한다는 것을 알게 될 것입니다.
Frank Shearar

13

당신은 매우 가깝습니다. 이 약간 다른 방식으로 생각하십시오.

  1. 내가 필요로하는 새로운 행동을 생각해보십시오.
  2. 그 행동에 대한 테스트를 만듭니다.
  3. 실패 테스트.
  4. 새로운 방법을 쓰거나 기존 방법을 확장하십시오.
  5. 합격 시험.
  6. 리 팩터 코드.
  7. 반복.

모든 속성에 대해 getter 및 setter를 자동으로 생성하지 마십시오 . 전체적인 방법을 생각하지 말고 모든 기능을 다루는 테스트를 작성하십시오 . 클래스 내에서 속성을 캡슐화하고 필요한 동작을 제공하는 메서드를 작성하십시오. 분석법을 미리 계획하지 않고 좋은 디자인으로 발전 시키십시오. TDD는 테스트 프로세스가 아니라 디자인 프로세스입니다. 다른 설계 프로세스보다 장점은 휴지통에 넣은 종이 대신 자동 회귀 테스트 스트림을 남기는 것입니다.

또한 Bob 아저씨의 세 가지 TDD 규칙을 기억하십시오 .

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

1
@ Zexanima : 당신은 우리 대부분이 1 년 후보다 더 잘하고 있습니다. 다음 단계를 지시하려고합니다.
pdr

2
나는 당신이이 세 가지 규칙을 연결한다고 생각합니다. 그들이 목가적으로 들리는 것처럼, 누구나 만나게 될 모든 생산 공장의 99 %에서 예외적으로 독단적이고 비현실적으로 단단합니다.

1
@FrankShearar 또는 그것은 근본주의 극단 주의자와 도매의 비현실적인 비난 으로 간주 될 수있다. 나는이 독단적 인 태도를 가진 상점에서 일했고, 그들은 교리를 문자 그대로 받아들이고 그 요점을 놓쳤다. 실제 코드를 실제로 테스트하지 않은 테스트를 작성하고 Mocking and Dependency Injection 프레임 워크 테스트만으로 중요한 것을 혼동시킬 수 있습니다.

1
@pdr 무언가의 정신은 그에 대한 교리 적으로 공식화 된 정식화에 정반대입니다. 철학 을 가지고 종교 로 바꾸는 것은 또 다른 일 입니다. TDD는 흑백 독단적 종교 용어로 대화하지 않는 것보다 더 많습니다 . 3 규칙이 그 소리를 독단적 및 프리젠 테이션 종교와 무엇을 들었 도착하면입니다 시험, 시험, 시험 영업 이익 같은 사람으로, 진언, 그들을 그대로 좋은보다는 그 원인을 더 해. 나는 양극성 진술이 이익보다 원인에 더 해를 끼칠 수 있다고 Frank에게 반박했다.

2
나의 요점은 교리가 무엇인가맹목적으로 복음으로 받아들이 는 데서 온다는 것이다 . 편광판을 가져 와서 사용해보십시오. 데이터가 없기 때문에 3 점 전체 또는 전혀 극단적 인 접근 방식을 시도하지 않으면 TDD와 관련된 트레이드 오프를 평가할 수 없습니다 .
Frank Shearar

5

다른 사람의 답변에 추가해야 할 사항 :

  1. 과도한 테스트와 같은 것이 있습니다. 단위 테스트가 가능한 한 겹치지 않도록하려고합니다. 동일한 코드에서 동일한 테스트 조건을 여러 번 테스트 할 필요는 없습니다. 반면, 프로덕션 코드를 리팩토링하고 해당 섹션과 겹치는 많은 테스트가있는 경우 모든 테스트를 되돌아 가서 수정해야합니다. 겹치지 않으면 한 번의 변경으로 최대 하나의 테스트 만 중단됩니다.

  2. 테스트를 작성하는 더 좋은 방법을 생각했기 때문에 다시 돌아가서 다시 쓰지 않을 것입니다. 이것은 같은 클래스 / 기능을 계속 작성하고 다시 작성하는 사람들에게 완벽하게 되려고 노력하고 있습니다. 그것은 완벽하지 않을 것이므로 계속하십시오. 더 나은 방법을 발견하면 마음의 뒤에 보관하십시오 (또는 테스트 의견에 추가). 다음에 당신이 거기에 있고, 새로운 방식으로 전환하는 것의 즉각적인 이점을 볼 때, 그것은 리팩토링 할 때입니다. 그렇지 않은 경우, 기능이 완료된 후 모든 기능이 작동하면 그대로 두십시오.

  3. TDD는 모든 기능을 테스트 할 수 있도록하는 것이 아니라 즉각적인 가치 제공에 중점을 둡니다. 기능을 추가 할 때는 "클라이언트에 필요한 것"을 묻는 것으로 시작하십시오. 그런 다음 클라이언트에게 필요한 것을 제공하는 인터페이스를 정의하십시오. 그런 다음 테스트 통과에 필요한 모든 것을 구현하십시오. TDD는 단순히 공용 기능을 코딩하고 각각의 기능을 테스트하는 것이 아니라 유스 케이스 시나리오 (모든 "가정"포함)를 테스트하는 것과 거의 같습니다.

  4. GUI 코드 테스트에 대해 질문했습니다. "Humble Dialog"및 "MVVM"패턴을 찾으십시오. 이 두 가지의 기본 개념은 실제로 UI 특정 논리가없는 "뷰 모델"클래스 세트를 작성한다는 것입니다. 그러나이 클래스에는 일반적으로 UI의 일부인 모든 비즈니스 논리가 있으며이 클래스는 100 % 테스트 가능해야합니다. 남은 것은 매우 얇은 UI 셸입니다. 예, 일반적으로 셸은 테스트 범위없이 남아 있지만 그 시점에는 거의 로직이 없어야합니다.

  5. 기존 코드의 많은 부분이 있다면, 다른 사람들이 제안한 것처럼 거의 모든 곳에서 단위 테스트를 추가하지 마십시오. 그것은 당신을 영원히 데려 갈 것이고 당신은 안정적이고 가까운 미래 (또는 그렇지 않은) 미래에는 변하지 않을 클래스의 80 %에 단위 테스트를 추가 할 때 이점을 얻지 못할 것입니다. 그러나 새로운 작업의 경우 모든 코드와 함께 TDD 개발을 사용하면 매우 유익합니다. 완료되면 자동화 된 테스트가 포함 된 제품군을 제공 할뿐만 아니라 실제 개발에 큰 이점이 있습니다.

    • 테스트 가능성을 고려하여 결합이 적고 모듈성이 더 높은 코드를 작성합니다.
    • 다른 무엇보다 먼저 공개 계약을 고려하면 훨씬 깨끗한 공용 인터페이스가 생깁니다.
    • 코드를 작성할 때 전체 기능을 실행하고 올바른 경로로 강제 실행하려고 시도하는 것과 비교하여 새 기능을 확인하는 데 밀리 초가 걸립니다. 우리 팀은 여전히 ​​올바른 조건 집합을 얻을 수 없기 때문에 한 번도 실행되지 않은 오류 처리 코드를 릴리스합니다. 나중에 QA에서 이러한 조건이 발생하면 얼마나 많은 시간을 낭비하는지 놀랍습니다. 그렇습니다.이 코드의 많은 부분은 누군가가 "연기 테스트가 끝나면 미래에 많은 변화를위한 영역이 아닌"것으로 간주했을 것입니다.

1

테스트되지 않는 몇 가지 방법, 즉 해당 테스트가 있습니다. 그러나 초기 코드가 작성된 후 추가되는 일부 테스트 (예 : 단일 조건에 대해 여러 테스트를 수행 할 수 있도록 경계 조건 및 기타 값)가 있습니다.

코드를 과도하게 테스트 할 수는 있지만 일반적으로 누군가가 입력과 관련된 모든 순열을 테스트하려고하는 곳에서 발생합니다. 예를 들어, 문자를받는 메소드가있는 경우 입력 할 수있는 모든 가능한 값에 대한 테스트를 작성합니까? 그것은 당신이 과도하게 테스트 할 곳입니다, IMO.


알았어 그게 내가하는 일이 아닙니다. 나는 보통 초기 테스트를 한 후에 방법을 테스트 할 수있는 다른 상황을 생각하게됩니다. 나는 그 '추가'테스트가 가치가 있는지 또는 그것이 끝났는지 확인하고있었습니다.
cgasser

충분히 작은 단위로 작업하면 일반적 으로 테스트가 실제로 작동하는지 확실하게 알 수 있습니다 . 다시 말해, 테스트 실패 (올바른 이유로!) 자체가 테스트를 테스트하는 것입니다. 그러나 "합리적으로 확실"한 수준은 테스트중인 코드만큼 높지 않습니다.
Frank Shearar

1

일반적으로 당신은 올바르게하고 있습니다.

테스트는 코드입니다. 따라서 테스트를 개선 할 수 있다면 계속해서 리팩토링하십시오. 테스트를 개선 할 수 있다고 생각되면 계속 변경하십시오. 테스트를 더 나은 테스트로 바꾸는 것을 두려워하지 마십시오.

코드 테스트에서 코드가 수행하는 방식을 지정하지 않는 것이 좋습니다. 테스트는 방법의 결과를 살펴 봐야합니다. 리팩토링에 도움이됩니다. 일부 메소드는 명시 적으로 테스트 할 필요가 없습니다 (예 : 단순 게터 및 세터).이 메소드를 사용하여 다른 테스트 결과를 확인할 수 있습니다.


나는 게터와 세터에 대한 테스트를 작성하고 있었으므로 그 팁에 감사드립니다. 불필요한 작업을 절약 할 수 있습니다.
cgasser

"일부 메소드는 명시 적으로 테스트 할 필요가 없습니다 (예 : 간단한 getter 및 setter)"-getter 및 setter를 복사 / 붙여 넣은 후 필드 이름을 변경하는 것을 잊어 버린 적이 있습니까? 간단한 코드에 대한 것은 간단한 테스트가 필요하다는 것입니다. 실제로 얼마나 많은 시간을 절약하고 있습니까?
pdr

나는 그 방법이 테스트되지 않았다는 것을 의미하지는 않는다. 다른 방법이 설정되어 있는지 확인하거나 실제 테스트 설정 중에 확인합니다. 게터 또는 세터가 제대로 작동하지 않으면 속성이 올바르게 설정되지 않았기 때문에 테스트가 실패합니다. 암시 적으로 무료로 테스트를받습니다.
Schleis

Getter 및 Setter 테스트는 오래 걸리지 않으므로 계속 수행 할 것입니다. 그러나 코드를 복사하여 붙여 넣지 않으므로 해당 문제가 발생하지 않습니다.
cgasser

0

TDD에 대한 저의 의견은 툴링이 '포인트 앤 클릭'스타일 개발자의 세계를 창조했다는 것입니다. 도구가 각 메소드에 대해 테스트 스텁을 작성한다고해서 모든 메소드에 대해 테스트를 작성해야하는 것은 아닙니다. 어떤 사람들은 TDD를 BDD (행동 중심 개발)로 '이름 바꾸기'하고 있는데, 테스트는 훨씬 더 세분화되어 있으며 각 방법이 별다른 방법이 아니라 클래스의 동작을 테스트하기위한 것입니다.

클래스를 의도 한대로 테스트하도록 테스트를 디자인하면, 특히 각 메소드보다 약간 더 많은 테스트를 작성하기 시작할 때, 특히 이들의 상호 작용을 테스트하기 시작할 때 몇 가지 이점이 있습니다. 행동 양식. 메소드가 아닌 클래스에 대한 테스트를 작성하는 것으로 생각할 수 있다고 생각합니다. 어쨌든, 방법을 조합하여 사용하는 방식에 모순이나 갈등이 없는지 확인하기 위해 여러 방법을 조합 한 '수락 테스트'를 작성해야합니다.

TDD를 테스트와 혼동하지 마십시오. 그렇지 않습니다. TDD는 메소드를 테스트하지 않고 요구 사항을 실행하기위한 코드를 작성하도록 설계되었습니다. 미묘하지만 중요한 점은 모든 방법에 대해 맹목적으로 테스트 코드를 작성하는 사람들에게 종종 손실됩니다. 작성한 코드가 예상대로 작동하지 않고 코드가 원하는대로 작동하는지 확인하는 테스트를 작성해야합니다.

BDD v TDD에 대한 올바른 링크가 있습니다. 한번 봐봐.


0

TDD를 배우기 시작할 때 , 그렇습니다. 실패한 테스트 통과를 제외하고 한 줄의 코드를 작성하지 않고 테스트에 실패 할 정도로만 작성하는 (그리고 올바른 / 예상적인 이유로 실패) 교리적인 접근 방식을 맹목적으로 따라야합니다. .

TDD가 무엇인지 알게되면 특정 종류의 테스트 할 가치가 없다고 결정할 수 있습니다. 이것은 당신이 모든 것에 대해 따라야하는 동일한 접근법이며, 일본 무술은 이것을 " 슈 하리 " 라고 부릅니다 . (이 링크는 또한 교사없이 학습 단계를 진행하는 방법을 설명합니다.


0

나는 당신이 과대 평가하고 있다고 믿는다.

나는 수년간 TDD를 연습 해 왔으며 경험상 TDD가 효과적으로 수행되면 두 가지 주요 이점이 있습니다.

  • 빠른 피드백 제공
  • 리팩토링 사용

빠른 피드백 제공

특히 동적 언어를 사용하면 1 초 이내에 관련 테스트를 실행할 수 있습니다. 소스 파일이 디스크에서 변경되면 파일 시스템 감시자가 이러한 테스트를 자동으로 실행합니다. 따라서 테스트 대기 시간이 거의 없으며, 작성한 코드가 예상대로 수행되었는지 즉시 알 수 있습니다. 따라서 TDD는 매우 효율적인 작업 방식으로 이어집니다.

리팩토링 사용

테스트 스위트가 좋은 경우 시스템 설계 방법에 대한 새로운 통찰력을 얻을 수 있으므로 안전하게 리팩토링 할 수 있습니다.

좋은 테스트 스위트를 사용하면 코드에서 책임을지고 이동 후 코드가 예상대로 작동한다고 확신 할 수 있습니다. 그리고 테스트 코드를 약간만 변경하면이 작업을 수행 할 수 있습니다.

시스템의 모든 메소드에 대한 테스트를 작성하는 경우 코드를 쉽게 리팩터링 할 수 없으며 코드 리 팩터마다 테스트 코드를 크게 변경해야합니다. 테스트 코드가 여전히 예상대로 작동하는지 확인할 수 있습니까? 아니면 실수로 테스트 코드에 버그를 도입하여 결과적으로 프로덕션 코드에 버그가 발생 했습니까?

그러나 pdr 's answer 에서 제안한 것처럼 테스트를 작성할 때 메소드 대신 동작에 중점을 두면 시스템 리팩토링시 변경이 훨씬 적은 테스트가 수행됩니다.

또는 Ian Cooper 가이 프레젠테이션 에서 말한 것처럼 (메모리에서 인용 했으므로 올바르게 인용되지 않을 수 있습니다) :

새로운 테스트를 작성하는 이유는 새로운 클래스를 추가하지 않고 새로운 행동을 추가해야합니다.


-2

모든 공개 방법을 테스트해야합니다 .

여기서 중요한 것은 공개 방법이 매우 작은 경우 너무 많은 정보를 노출하고 있다는 것입니다. 모든 속성을 getXXX()실제로 노출하는 일반적인 관행은 캡슐화를 깨뜨립니다.

공용 메소드가 실제로 클래스의 동작 인 경우 테스트해야합니다. 그렇지 않은 경우, 그들은 좋은 공개 방법이 아닙니다.

편집 : pdr의 대답 은 내 것보다 훨씬 완벽합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.