TDD가없는 단위 테스트의 의미


28

우리는 TDD를 사용하여 개발할 계획 인 새로운 프로젝트를 시작했습니다.

TDD에 대한 아이디어는 실패했지만 (많은 비즈니스 및 비 비즈니스 이유), 지금 우리는 대화를합니다. 어쨌든 단위 테스트를 작성해야하는지 여부입니다. 제 친구는 TDD없이 단위 테스트를 작성하는 데 아무런 의미가 없거나 0에 가깝다고 말합니다. 통합 테스트에만 중점을 두어야합니다. 나는 반대로 미래 코드를 만들기 위해 일반 단위 테스트를 작성하는 데 여전히 의미가 있다고 생각합니다. 어떻게 생각해?

추가 : 나는 이것이이 질문 의 사본이 아니라고 생각합니다. << -UT와 TDD의 차이점을 이해합니다. 내 질문은 차이점관한 것이 아니라 TDD없이 단위 테스트를 작성 하는 감각관한 것 입니다.


22
나는 당신의 친구가 그런 터무니없는 입장에 대해 어떤 추론을 가지고 있는지 궁금합니다.
Telastyn

11
단위 테스트를 거친 대부분의 프로젝트에서 TDD를 사용 하지 않는 것으로 나타났습니다 .
Casey

2
통합 수준은 어떻게 되나요? 당신의 단위는 무엇입니까? 각 테스트 수준 아래에서 얼마나 자주 리팩토링합니까? 통합 테스트는 얼마나 빨리 진행됩니까? 그들이 쓰는 것이 얼마나 쉬울까요? 코드의 다른 부분에서 몇 개의 조합 사례가 생성됩니까? 등등 ... 이것에 대한 답을 모른다면, 결정을 내리기가 너무 이르다. 때때로 TDD는 훌륭합니다. 때로는 이점이 명확하지 않습니다. 때로는 단위 테스트가 필수적입니다. 적절한 통합 테스트 세트를 구입하는 경우가 많고 훨씬 융통성이 있습니다. 옵션을 계속 열어 두십시오.
topo Reinstate Monica

2
TDD를 하지 않으면 경험을 통한 실질적인 조언으로 모든 것을 테스트하지 마십시오 . 어떤 종류의 테스트가 유용한 지 결정하십시오. 순수한 입력 / 출력 방법에 대한 단위 테스트는 엄청나게 가치있는 반면, 매우 높은 수준의 응용 프로그램 (예 : 실제로 웹 응용 프로그램에서 웹 요청을 보내는 경우)에서의 통합 테스트도 매우 중요하다는 것을 알았습니다. 많은 모의 설정이 필요한 중간 계층 통합 테스트 및 단위 테스트를 살펴보십시오. 또한이 비디오를 시청 : youtube.com/watch?v=R9FOchgTtLM를 .
jpmc26

요청하신 질문과 관련하여 업데이트가 적합하지 않습니다. TDD와 단위 테스트의 차이점을 이해한다면 단위 테스트 작성을 방해하는 것입니다. 질문을 닫아두기로 한 투표는 "닫는 대신"무엇을 묻고 있는지 불분명하다 "는 결론을 내릴 수 있습니다.

답변:


52

TDD는 주로 (1) 적용 범위를 보장하고 (2) 유지 보수 가능하고 이해 가능하며 테스트 가능한 설계를 추진하기 위해 사용됩니다. TDD를 사용하지 않으면 코드 범위가 보장되지 않습니다. 그러나 결코 그 목표를 포기하고 0 % 적용 범위를 유지해야한다는 의미는 아닙니다.

이유로 회귀 테스트가 개발되었습니다. 그 이유는 장기적으로 더 많은 노력을 기울이는 것보다 더 많은 시간을 절약 할 수 있기 때문입니다. 이것은 계속해서 입증되었습니다. 따라서, 당신은 심각하게 조직 회귀 테스트를 추천 모든 지도자보다는 소프트웨어 엔지니어링에 훨씬 더 많은 것을 확신하지 않는 한 (또는 곧 그래서이 것을 내려 갈 계획하는 경우 입니다 더 장기적으로 당신을 위해) 예, 당신 통합 테스트보다 오류를 조기에 포착하여 비용을 절감 할 수 있기 때문에 전 세계 거의 모든 다른 조직에 적용되는 정확한 이유로 단위 테스트를 수행해야합니다. 그것들을 쓰지 않는 것은 단지 거리에 누워있는 무료 돈을 넘기는 것과 같습니다.


12
"TDD를 사용하지 않으면 보장 된 코드 범위를 얻을 수 없습니다.": 나는 그렇게 생각하지 않습니다. 이틀 동안 개발할 수 있고 다음 이틀 동안 테스트를 작성합니다. 중요한 요점은 원하는 코드 적용 범위가 될 때까지 기능이 완료된 것으로 간주하지 않는다는 것입니다.
Giorgio

5
@DougM-이상적인 세상에서 ...
Telastyn

7
안타깝게도 TDD는 조롱 과 함께 일하며 사람들이 그 일을 그만 둘 때까지 테스트가 더 빨리 실행된다는 입니다. TDD가 종료되었습니다. 긴 라이브 테스트.
MickyD

17
TDD 는 코드 범위를 보장하지 않습니다. 그것은 위험한 가정입니다. 테스트에 대해 코딩하고 테스트를 통과 할 수는 있지만 여전히 우세한 사례가 있습니다.
Robert Harvey

4
@MickyDuncan 나는 당신의 우려를 완전히 이해하지 못합니다. Mocking은 한 구성 요소를 다른 구성 요소와 격리하는 데 사용되는 완벽하게 유효한 기술이므로 해당 구성 요소의 동작을 독립적으로 테스트 할 수 있습니다. 그렇습니다. 극단적으로 받아들이면 과도하게 엔지니어링 된 소프트웨어로 이어질 수 있지만 부적절하게 사용되는 경우 모든 개발 기술도 가능합니다. 또한 DHH가 언급 한 기사에서 언급했듯이 전체 시스템 테스트 만 사용한다는 아이디어는 실제로 나쁘지는 않지만 나쁘지 않습니다. 특정 기능을 테스트하는 가장 좋은 방법이 무엇인지 결정하려면 판단을 사용하는 것이 중요합니다 .
Jules

21

에게 지금 진행되고있는 일에서 관련 일화가 있습니다 . TDD를 사용하지 않는 프로젝트를 진행 중입니다. 우리의 QA 직원들은 우리를 그 방향으로 움직이고 있지만, 우리는 작은 복장이며 오래 걸리는 과정이었습니다.

어쨌든 최근에는 타사 라이브러리를 사용하여 특정 작업을 수행했습니다. 해당 라이브러리의 사용과 관련하여 문제가 있었으므로 본질적으로 동일한 라이브러리의 버전을 직접 작성해야했습니다. 전체적으로 약 5,000 줄의 실행 코드와 약 2 개월이 걸렸습니다. 나는 코드 라인이 좋지 않은 메트릭이라는 것을 알고 있지만이 답변에 대해서는 괜찮은 규모의 지표라고 생각합니다.

임의의 비트 수를 추적 할 수있는 특정 데이터 구조가 필요했습니다. 프로젝트가 Java로되어 있기 때문에 Java를 선택 BitSet하고 조금 수정했습니다 (리딩을 추적하는 기능이 필요했습니다 0.Java의 BitSet은 어떤 이유로 .....)하지 않습니다. 적용 범위가 ~ 93 %에 도달 한 후 실제로 작성한 시스템에 스트레스를주는 몇 가지 테스트를 작성하기 시작했습니다. 기능의 특정 측면을 벤치마킹하여 최종 요구 사항에 충분히 빠르도록해야했습니다. 당연히 BitSet인터페이스 에서 재정의 된 기능 중 하나는 큰 비트 세트 (이 경우 수백만 비트)를 처리 할 때 엄청나게 느 렸습니다. 다른 재정의 된 기능은이 기능에 의존하므로 병목 이 컸습니다 .

내가하고있는 드로잉 보드에 가고, 그리고 기본 구조 조작 할 수있는 방법 파악되었다 결국 무엇 BitSet입니다 long[]. 알고리즘을 설계하고 동료에게 입력을 요청한 다음 코드 작성에 대해 설정했습니다. 그런 다음 단위 테스트를 실행했습니다. 그들 중 일부는 고장 났고, 그것을 고치기 위해 알고리즘을 어디에서 찾아야하는지 정확하게 지적한 것입니다. 단위 테스트의 모든 오류를 수정 한 후에는 기능이 제대로 작동한다고 말할 수있었습니다. 최소한이 알고리즘이 이전 알고리즘과 마찬가지로 작동한다고 확신 할 수 있습니다.

물론 이것은 방탄이 아닙니다. 내 코드에 단위 테스트가 확인하지 않는 버그가 있으면 알 수 없습니다. 그러나 물론 동일한 버그가 느린 알고리즘에도 있었을 수 있습니다. 그러나 특정 기능의 잘못된 출력에 대해 걱정할 필요가 없다고 확신 할 수 있습니다. 기존의 단위 테스트는 새로운 알고리즘을 테스트하여 올바른지 확인하는 데 몇 시간, 며칠이 걸리지 않았습니다.

, TDD에 관계없이 단위 테스트를 수행해야하는 시점입니다. , 단위 테스트는 코드 리팩토링 / 유지 관리가 끝날 때 TDD와 TDD 외부에서 모두 동일하게 수행합니다. 물론 이것은 정기적 인 회귀 테스트, 연기 테스트, 퍼지 테스트 등과 쌍을 이루어야하지만 단위 상태는 이름에서 알 수 있듯이 가장 작은 원자 수준에서 사물을 테스트하여 오류가 발생한 위치를 알려줍니다.

필자의 경우 기존 단위 테스트가 없으면 알고리즘이 항상 작동하도록하는 방법을 고안해야합니다. 결국 , 단위 테스트 와 비슷한 소리가 들리지 않습니까?


7

코드를 대략 4 가지 범주로 나눌 수 있습니다.

  1. 간단하고 거의 변경되지 않습니다.
  2. 간단하고 자주 변경됩니다.
  3. 복잡하고 거의 변경되지 않습니다.
  4. 복잡하고 자주 변경됩니다.

단위 테스트는 목록 아래로 내려 갈수록 더 중요해집니다 (중요한 버그를 잡을 수 있음). 개인 프로젝트에서는 거의 항상 카테고리 4에서 TDD를 수행합니다. 카테고리 3에서는 수동 테스트가 더 간단하고 빠르지 않은 한 일반적으로 TDD를 수행합니다. 예를 들어 앤티 앨리어싱 코드는 작성하기가 복잡하지만 단위 테스트를 작성하는 것보다 시각적으로 확인하기가 훨씬 쉬우므로 해당 코드가 자주 변경되는 경우 단위 테스트만으로도 가치가 있습니다. 나머지 코드는 해당 함수에서 버그를 찾은 후에 만 ​​단위 테스트를 거쳤습니다.

특정 코드 블록이 어떤 범주에 속하는지 미리 알기 어려운 경우가 있습니다. TDD의 가치는 실수로 복잡한 단위 테스트를 놓치지 않는 것입니다. TDD 비용은 간단한 단위 테스트 작성에 소요되는 시간입니다. 그러나 일반적으로 프로젝트 경험이있는 사람들은 코드의 다른 부분이 어떤 범주에 적합한 지 확실하게 알고 있습니다. TDD를 수행하지 않는 경우 최소한 가장 유용한 테스트를 작성해야합니다.


1
앤티 앨리어싱 예제에서 제안한 것처럼 코드를 작업 할 때 가장 좋은 방법은 코드를 실험적으로 개발 한 다음 나중에 알고리즘이 실수로 중단되지 않도록 특성화 테스트 를 추가 하는 것입니다. 특성화 테스트는 매우 빠르고 개발하기 쉬우므로 오버 헤드가 매우 적습니다.
Jules

1

단위 테스트, 구성 요소 테스트, 통합 테스트 또는 수락 테스트 등 중요한 부분은 자동화되어야한다는 것입니다. 자동화 된 테스트가없는 것은 간단한 CRUD에서 가장 복잡한 계산에 이르기까지 모든 종류의 소프트웨어에 치명적인 실수입니다. 그 이유는 자동화 된 테스트를 작성하면 항상 그렇지 않은 경우 수동으로 모든 테스트를 수동으로 실행해야하는 지속적인 비용보다 비용이 적게 들기 때문입니다. 당신이 그들을 작성 한 후, 당신은 그들이 통과 또는 실패 여부를 확인하기 위해 버튼을 눌러야합니다. 수동 테스트는 항상 실행하는 데 시간이 오래 걸리고 테스트에 통과했는지 실패하는지 확인할 수있는 사람 (지루하고 주의력이 부족한 살아있는 생물체)에 의존합니다. 요컨대, 항상 자동 테스트를 작성하십시오.

이제 동료가 TDD없이 모든 종류의 단위 테스트를 수행하지 못하는 이유에 대해서는 프로덕션 코드 이후에 작성된 테스트를 신뢰하기가 더 어려울 수 있습니다. 자동화 된 테스트를 신뢰할 수 없으면 아무 가치가 없습니다 . TDD주기 이후에는 먼저 테스트 실패 (올바른 이유로)를 통과하여 프로덕션 코드를 작성하여 통과시키지 못하도록해야합니다. 이 프로세스는 본질적으로 테스트를 테스트하므로 신뢰할 수 있습니다. 실제 코드보다 먼저 테스트를 작성하면 유닛과 구성 요소를보다 쉽게 ​​테스트 할 수 있도록 설계 할 수 있다는 사실 (높은 수준의 디커플링, SRP 적용 등)이 있습니다. 물론 TDD를 수행하는 데는 훈련 이 필요 합니다 .

대신, 모든 프로덕션 코드를 먼저 작성하면 테스트를 작성할 때 첫 실행시 통과 할 것으로 예상됩니다. 올바른 동작을 주장하지 않고 커버 생산 코드의 100 %를, (심지어 어떤 주장을 수행 할 수는!하는 테스트 만든 수 있기 때문에 이것은 매우 문제가 내가 이런 일이 본 적이을 ) 당신이 실패 볼 수 없기 때문에, 올바른 이유로 실패했는지 먼저 확인하십시오. 따라서 오 탐지가있을 수 있습니다. 거짓 양성은 결국 테스트 스위트에 대한 신뢰를 잃어 본질적으로 사람들이 수동 테스트에 다시 의존하도록 강요하므로 두 프로세스 (작성 테스트 + 수동 테스트)의 비용이 발생합니다.

즉 , TDD처럼 테스트테스트 할 다른 방법을 찾아야 합니다 . 따라서 테스트를 신뢰할 수 있도록 디버깅, 프로덕션 코드의 일부에 주석 처리 등을 사용합니다. 문제는 "테스트 테스트"프로세스가이 방법으로 훨씬 느리다는 것입니다. 이 시간을 수동으로 (프로덕션 코드를 코딩하는 동안 자동 테스트를 수행하지 않기 때문에) 수동 테스트를 실행하는 시간에 추가하면 내 경험상 전체 프로세스가 연습보다 훨씬 느립니다. "책으로"TDD (Kent Beck-TDD by Example). 또한, 여기에 베팅하고 기꺼이 작성한 "테스트 테스트" 는 TDD보다 훨씬 더 많은 훈련 이 필요하다고 말하고 싶습니다 .

따라서 팀에서 TDD를 수행하지 않은 "비즈니스 및 비 비즈니스 이유"를 재고 할 수 있습니다. 내 경험상 사람들은 코드가 완료된 후 단위 테스트를 작성하는 것보다 TDD가 느리다고 생각하는 경향이 있습니다. 위에서 읽은 것처럼이 가정에는 결함이 있습니다.


0

종종 테스트 품질은 출처에 따라 다릅니다. 나는 '실제적인'TDD를하지 않는 것에 대해 정기적으로 죄책감을 느낀다. 나는 내가 사용하고 싶은 전략이 실제로 작동한다는 것을 증명하기 위해 몇 가지 코드를 작성하고, 그 후에 코드가 테스트를 지원하도록 의도 된 각 사례를 다룬다. 일반적으로 코드 단위는 클래스이므로 테스트 범위 없이도 얼마나 많은 작업을 수행 할 것인지에 대한 일반적인 아이디어를 제공합니다. 이것이 의미하는 것은 테스트의 시맨틱 의미가 '완료된'상태에서 테스트중인 시스템과 잘 일치한다는 것입니다. SUT가 어떤 경우를 충족시키고 어떻게 이행 하는지를 알고 있었기 때문입니다.

반대로 공격적인 리팩토링 정책을 사용하는 TDD는 테스트 변경중인 시스템의 공용 인터페이스처럼 작성할 수있는 속도만큼 테스트를 더 이상 사용하지 않는 경향이 있습니다. 나는 개인적으로 두 응용 프로그램의 기능 단위를 설계하는 정신적 작업 부하 발견 하고 내 농도와 빈도가 미끄러 테스트 유지 보수를 유지하기 위해 너무 높은 것으로 동기화를 커버 테스트의 의미를 유지합니다. 코드베이스는 가치있는 것을 테스트하지 않거나 명백한 잘못 된 테스트로 끝납니다. 테스트 스위트를 최신 상태로 유지할 수있는 훈련과 정신 능력이 있다면 , TDD를 원하는만큼 엄격하게 연습하십시오. 나는 그렇지 않기 때문에 그 이유로 인해 성공하지 못했습니다.


0

실제로 Bob 아저씨는 Clean Coders 비디오 중 하나에서 매우 흥미로운 점을 언급했습니다. 그는 Red-Green-Refactor주기는 두 가지 방법으로 적용될 수 있다고 말했다.

첫 번째는 기존의 TDD 방식입니다. 실패한 테스트를 작성한 다음 테스트를 통과하고 리팩터링하십시오.

두 번째 방법은 매우 작은 생산 코드를 작성하고 즉시 단위 테스트를 통해 리팩터링하는 것입니다.

아이디어는 아주 작은 단계로 진행하는 것입니다. 물론 프로덕션 코드에서 테스트가 빨간색에서 녹색으로 진행되었다는 확인을 잃어 버렸지 만 TDD를 이해하려고 시도조차하지 않은 주니어 개발자와 주로 일한 경우에는 다소 효과적이었습니다.

다시 한 번 반복합니다 (Bob 아저씨가 강조했습니다). 아이디어는 아주 작은 단계를 거쳐 방금 추가 된 생산 코드를 즉시 테스트하는 것입니다.


"... 아이디어는 아주 작은 단계를 거쳐 방금 추가 된 생산 코드를 즉시 테스트하는 것입니다.": 동의하지 않습니다. 무엇을하고 싶은지 이미 알고 있고 세부 사항을 다루고 싶을 때 좋은 점을 설명하지만 먼저 큰 그림을 얻어야합니다. 그렇지 않으면 매우 작은 단계 (테스트, 개발, 테스트, 개발)를 수행하면 세부 정보가 손실 될 수 있습니다. "가는 곳을 모른다면 그곳에 가지 않을 수 있습니다."
Giorgio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.