실제 코드보다 테스트를 작성하는 데 많은 시간을 소비하는 것이 일반적입니까?


211

테스트하는 실제 코드보다 테스트가 훨씬 까다 롭고 작성하기가 어렵다는 것을 알았습니다. 테스트하는 코드보다 테스트를 작성하는 데 더 많은 시간을 소비하는 것은 드문 일이 아닙니다.

이것이 정상입니까 아니면 내가 잘못하고 있습니까?

단위 테스트 또는 테스트 중심 개발이 가치가 있습니까? ”,“ 시스템 자체를 구현하는 것보다 기능 테스트를 구현하는 데 더 많은 시간을 보내고 있습니다. 이것이 정상입니까? ”및 그들의 답변은 테스트의 가치가 있는지 여부에 관한 것입니다 ( "테스트 작성은 생략해야합니까?"). 테스트가 중요하다고 확신하지만 실제 코드보다 테스트에 더 많은 시간을 쓰는 것이 정상적인 지 아니면 나만인지 궁금합니다.

내 질문에 대한 견해, 답변 및 투표 수로 판단하면 웹 사이트의 다른 질문에서는 해결되지 않은 합법적 인 문제 만 가정 할 수 있습니다.


20
일화이지만 TDD 할 때 코드를 작성하는 것만 큼 테스트를 작성하는 데 거의 많은 시간을 소비합니다. 코드보다 테스트에 더 많은 시간을 보낸다는 사실을 알고 나서 테스트를 작성하고 글을 쓸 때입니다.
RubberDuck

10
또한 코드를 작성하는 것보다 더 많은 시간을 읽습니다.
Thorbjørn Ravn Andersen 님이

27
또한 테스트 실제 코드입니다. 고객에게 해당 부품을 배송하지 않습니다.
Thorbjørn Ravn Andersen 님이

5
코드를 작성하는 것보다 더 많은 시간을 실행하는 것이 이상적입니다. (그렇지 않으면 수작업으로 작업을 수행하면됩니다.)
Joshua Taylor

5
@RubberDuck : 여기에 반대되는 경험. 때로는 코드와 디자인이 이미 깔끔한 후에 테스트를 작성할 때 코드와 테스트를 너무 많이 다시 작성할 필요가 없습니다. 따라서 테스트를 작성하는 데 시간이 덜 걸립니다. 그것은 규칙이 아니지만 꽤 자주 발생합니다.
Giorgio

답변:


205

소프트웨어 엔지니어링 과정에서 개발 중 ~ 10 %는 새 코드 작성에 소비하고 나머지 90 %는 디버깅, 테스트 및 문서화라는 것을 기억합니다.

단위 테스트는 디버깅 및 테스트 노력을 (잠재적으로 자동화 가능한) 코드로 캡처하기 때문에 더 많은 노력이 필요하다는 것이 합리적입니다. 실제로 소요되는 시간은 테스트를 작성하지 않고 디버깅 및 테스트를 수행하는 것보다 훨씬 많지 않아야합니다.

마지막으로 테스트도 문서로 두 배가되어야합니다! 코드가 사용되는 방식으로 단위 테스트를 작성해야합니다. 즉, 테스트 (및 사용법)는 간단해야하며 구현에 복잡한 것을 넣으십시오.

테스트를 작성하기 어려운 경우 테스트 코드를 사용하기 어려울 수 있습니다!


4
코드가 테스트하기 어려운 이유를 살펴 보는 것이 좋은시기 일 수 있습니다. :) 대규모 중첩 이진 / 삼항 연산자와 같이 엄격하게 필요하지 않은 복잡한 다기능 행을 "롤링 해제"하려고합니다. 불필요한 불필요한 이진이 정말 싫어 경로 중 하나로 이진 / 삼항 연산자가있는 / ternary 연산자
Nelson

53
나는 마지막 부분에 동의하지 않기를 간청합니다. 매우 높은 단위 테스트 적용 범위를 목표로하는 경우, 코드의 의도 된 사용에 대해 드물고 때로는 완전한 사용 사례를 포함해야합니다. 이러한 경우에 대한 테스트 작성은 전체 작업에서 가장 많은 시간이 소요될 수 있습니다.
otto

나는 이것을 다른 곳에서 말했지만, 대부분의 코드는 일종의 "Pareto Principle"패턴을 따르는 경향이 있기 때문에 단위 테스팅이 훨씬 더 길어지는 경향이있다. 논리의 100 %를 처리합니다 (즉, 모든 에지 사례를 처리하는 데는 단위 테스트 코드의 약 5 배가 소요됨). 물론 프레임 워크에 따라 여러 테스트를 위해 환경을 초기화하여 필요한 전체 코드를 줄일 수 있지만 추가 계획이 필요합니다. 100 % 신뢰에 접근하려면 단순히 주요 경로를 테스트하는 것보다 훨씬 더 많은 시간이 필요합니다.
phyrfox

2
@phyrfox 나는 이것이 너무 조심 스럽다고 생각한다. "코드의 다른 99 %는 엣지 케이스"와 비슷하다. 이는 다른 99 %의 테스트가 이러한 경우에 해당함을 의미합니다.
Móż

@Nelson 중첩 된 삼항 연산자는 읽기 어렵다는 것에 동의하지만 테스트가 특히 어려워지는 것은 아니라고 생각합니다 (좋은 범위의 도구를 사용하면 가능한 조합 중 하나를 놓쳤는 지 알 수 있습니다). IMO, 소프트웨어는 너무 밀접하게 결합되거나 유선으로 연결된 데이터 또는 매개 변수로 전달되지 않은 데이터 (예 : 조건이 현재 시간에 의존하고 매개 변수로 전달되지 않는 경우)에 따라 테스트하기가 어렵습니다. 이것은 물론 코드가 "읽을 수있는"방법과 직접 관련이 없지만, 다른 모든 것들은 동일하지만 읽을 수있는 코드가 더 좋습니다!
Andres F.

96

그것은.

단위 테스트 만 수행하더라도 실제로 테스트 된 코드보다 더 많은 코드를 테스트에 포함시키는 것은 드문 일이 아닙니다. 아무 문제가 없습니다.

간단한 코드를 고려하십시오.

public void SayHello(string personName)
{
    if (personName == null) throw new NullArgumentException("personName");

    Console.WriteLine("Hello, {0}!", personName);
}

시험은 무엇입니까? 테스트 할 간단한 경우가 4 가지 이상 있습니다.

  1. 사람 이름은 null입니다. 실제로 예외가 발생합니까? 그것은 적어도 세 줄의 테스트 코드입니다.

  2. 사람 이름은 "Jeff"입니다. 우리 "Hello, Jeff!"는 응답을 받습니까? 그것은 네 줄의 테스트 코드입니다.

  3. 사람 이름은 빈 문자열입니다. 우리는 어떤 결과를 기대합니까? 실제 출력은 무엇입니까? 부수적 인 질문 : 기능 요구 사항과 일치합니까? 이는 단위 테스트를위한 또 다른 4 줄의 코드를 의미합니다.

  4. 사람 이름은 문자열에 비해 짧지 만 "Hello, "느낌표와 결합하기에는 너무 깁니다 . 어떻게 되나요? ¹

이를 위해서는 많은 테스트 코드가 필요합니다. 또한 가장 기본적인 코드 조각에는 테스트중인 코드에 필요한 객체를 초기화하는 설정 코드가 필요한 경우가 많으며, 종종 스텁 및 모의 작성 등으로 이어집니다.

비율이 매우 큰 경우 몇 가지 사항을 확인할 수 있습니다.

  • 테스트 전체에 코드 중복이 있습니까? 테스트 코드라는 사실이 유사한 테스트간에 코드를 복제 (복사 붙여 넣기)해야한다는 의미는 아닙니다. 이러한 복제로 인해 테스트 유지 관리가 어려워집니다.

  • 중복 테스트가 있습니까? 일반적으로 단위 테스트를 제거하면 분기 범위가 줄어 듭니다. 그렇지 않은 경우 경로가 이미 다른 테스트에 포함되어 있으므로 테스트가 필요하지 않음을 나타낼 수 있습니다.

  • 테스트해야 할 코드 만 테스트하고 있습니까? 타사 라이브러리 의 기본 프레임 워크테스트 할 필요는 없으며 프로젝트 코드 만 독점적 으로 테스트해야 합니다.

연기 테스트, 시스템 및 통합 테스트, 기능 및 승인 테스트 및 스트레스 및로드 테스트를 사용하면 더 많은 테스트 코드를 추가 할 수 있으므로 실제 코드의 모든 LOC에 대해 4-5 개의 LOC 테스트를 갖는 것은 걱정할만한 것이 아닙니다.

TDD에 대한 메모

코드를 테스트하는 데 걸리는 시간이 걱정된다면 코드를 잘못 작성했을 수 있습니다. 이 경우 TDD는 코드와 테스트간에 전환하여 15-45 초의 반복 작업을 장려함으로써 도움이 될 수 있습니다. TDD의 지지자에 따르면 필요한 테스트 수와 더 중요하게는 테스트를 위해 작성하고 특히 다시 작성 해야하는 비즈니스 코드의 양을 줄임으로써 개발 프로세스 속도를 높 입니다.


하자 ¹ N문자열의 최대 길이 . SayHello길이 n -1 의 문자열을 참조로 호출 하고 전달할 수 있습니다. 이 문자열은 정상적으로 작동합니다. 이제 Console.WriteLine단계에서 형식화는 길이가 n + 8 인 문자열로 끝나므로 예외가 발생합니다. 아마도 메모리 제한으로 인해 n / 2 문자를 포함하는 문자열조차도 예외가 발생할 수 있습니다. 질문해야 할 질문은이 네 번째 테스트가 하나의 단위 테스트인지 (하나는 비슷하지만 평균 단위 테스트에 비해 리소스 측면에서 훨씬 더 큰 영향을 줄 수 있음) 실제 코드 또는 기본 프레임 워크를 테스트하는지 여부입니다.


5
사람도 null이라는 이름을 가질 수 있다는 것을 잊지 마십시오. stackoverflow.com/questions/4456438/…
psatek

1
@JaMabRaihle @MainMa personName는 a 에 맞는 값을 의미 string하지만 personName연결된 값 에 더한 값은 오버플로 한다고 가정 합니다 string.
woz

@ JacobRaihle :이 점을 설명하기 위해 대답을 편집했습니다. 각주를 참조하십시오.
Arseni Mourzenko

4
As a rule of thumb, if you remove a unit test, the branch coverage should decrease.위에서 언급 한 네 가지 테스트를 모두 작성하고 세 번째 테스트를 제거하면 적용 범위가 줄어 듭니까?
Vivek

3
"충분히 길다"→ "너무 길다"(포인트 4)?
Paŭlo Ebermann

59

단위 테스트와 통합 / 수락 테스트라는 두 가지 유형의 테스트 전략을 구분하는 것이 중요하다고 생각합니다.

단위 테스트가 필요한 경우도 있지만, 종종 절망적으로 지나친 작업입니다. 이는 "100 % 적용 범위"와 같이 개발자에게 강요된 의미없는 메트릭으로 인해 악화됩니다. http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf 는 이에 대한 설득력있는 주장을 제공합니다. 공격적인 단위 테스트와 관련하여 다음 문제를 고려하십시오.

  • 비즈니스 가치를 문서화하지는 않지만 100 % 적용 범위에 근접하기 위해 존재하는 무의미한 테스트가 풍부합니다. 내가 일하는 곳에서는 새로운 클래스의 인스턴스를 만드는 것 외에는 아무것도하지 않는 팩토리 에 대한 단위 테스트를 작성해야합니다 . 가치가 없습니다. 또는 Eclipse에서 생성 된 긴 .equals () 메소드-테스트 할 필요가 없습니다.
  • 테스트를 쉽게하기 위해 개발자는 복잡한 알고리즘을 테스트 가능한 작은 단위로 세분화했습니다. 승리처럼 들리 죠? 공통 코드 경로를 따르기 위해 12 개의 클래스를 열어야하는 경우에는 아닙니다. 이 경우 단위 테스트를 통해 코드 가독성을 실제로 줄일 수 있습니다. 이것의 또 다른 문제점은 코드를 너무 작은 조각으로 자르면 다른 코드 조각의 하위 집합이 아닌 정당화되지 않는 클래스 (또는 코드 조각)의 크기로 끝납니다.
  • 적용 범위가 큰 코드를 리팩토링하는 것은 어려울 수 있습니다. 코드에 의존하는 단위 테스트도 풍부하게 유지해야하기 때문 입니다. 이것은 행동 단위 테스트에 의해 악화되며, 테스트의 일부는 클래스의 협력자 (일반적으로 조롱)의 상호 작용을 검증합니다.

반면에 통합 / 수락 테스트는 소프트웨어 품질에서 매우 중요한 부분이며, 제 경험상 소프트웨어를 올바르게 만드는 데 많은 시간을 할애해야합니다.

많은 상점들이 TDD 쿨 에이드를 마셨지 만, 위의 링크에서 알 수 있듯이 많은 연구에 따르면 그 이점이 결정적이지 않습니다.


10
리팩토링 포인트 +1 필자는 10여 년 동안 패치되고 막힌 레거시 제품을 작업했습니다. 특정 방법에 대한 종속성을 확인하려고하면 하루 중 더 나은 시간이 소요될 수 있으며,이를 조롱하는 방법을 찾으려면 시간이 더 오래 걸릴 수 있습니다. 5 줄짜리 변경이 200 줄 이상의 테스트 코드를 요구하는 것은 드문 일이 아니었고, 일주일 동안 더 나은 시간을 보냈습니다.
TMN

3
이. MainMa의 답변 테스트 4에서는 (학문적 맥락을 벗어나서) 실제로 수행되는 방법에 대해 생각하기 때문에 수행해서는 안됩니다. 사람의 이름이 문자열의 최대 크기에 가까워지면 무언가 잘못되었습니다. 테스트하지 마십시오. 대부분의 경우이를 감지하기위한 코드 경로가 없습니다. 적절한 응답은 프레임 워크가 기본 메모리 부족 예외를 발생시키는 것입니다. 이것이 실제 문제이기 때문입니다.
Móż

3
" .equals()Eclipse에서 생성 된 긴 메소드 를 테스트 할 필요가 없을 때까지 계속 응원합니다 ." 나는에 대한 테스트 환경을 작성 equals()하고 compareTo() github.com/GlenKPeterson/TestUtils 내가 부족했던 테스트 한 거의 모든 구현을. 어떻게하면 컬렉션을 사용합니까 equals()하고 hashCode()정확하고 효율적으로 함께 작동하지 않습니다? 나머지 답변에 대해 다시 응원하겠습니다. 난 것을 허용 일부 자동 생성 등호 () 메소드가 있습니다 테스트를 필요로하지,하지만 그것은 나를 긴장하게 가난한 구현과 많은 버그를 했어.
GlenPeterson

1
@GlenPeterson 동의합니다. 내 동료가이 목적을 위해 EqualsVerifier를 썼습니다. github.com/jqno/equalsverifier
Tohnmeister를

@ Ӎσᶎ 아니오, 여전히 수용 할 수없는 입력을 테스트해야합니다. 이것이 사람들이 보안 공격을 찾는 방법입니다.
gbjbaanb

11

일반화 할 수 없습니다.

물리 기반 렌더링에서 공식이나 알고리즘을 구현해야하는 경우, 가장 작은 버그 나 정밀도가 몇 달 후 진단하기 어려운 버그로 이어질 수 있다는 사실을 알고 편집증 단위 테스트에 10 시간을 소비 할 수 있습니다. .

논리적으로 일부 코드 줄을 그룹화하고 파일 범위에서만 사용되는 이름을 지정하려면 전혀 테스트하지 않을 수 있습니다 (예외없이 모든 단일 함수에 대한 테스트 작성을 고집하면 프로그래머가 폴백 할 수 있음) 가능한 적은 기능을 작성하는 것).


이것은 정말 귀중한 관점입니다. 질문에 완전히 대답하려면 더 많은 맥락이 필요합니다.
CLF

3

예, TDDing에 대해 이야기하는 것이 정상입니다. 자동화 된 테스트를 수행하면 원하는 코드 동작을 보호 할 수 있습니다. 먼저 테스트를 작성할 때 기존 코드에 이미 원하는 동작이 있는지 확인합니다.

이것은 다음을 의미합니다.

  • 실패한 테스트를 작성하면 가장 간단한 방법으로 코드를 수정하는 것이 테스트를 작성하는 것보다 짧습니다.
  • 통과하는 테스트를 작성하면 추가 코드를 작성할 필요가 없으므로 코드보다 테스트를 작성하는 데 더 많은 시간을 소비 할 수 있습니다.

(이는 후속 코드를 작성하는 데 걸리는 시간을 줄이는 것을 목표로하는 코드 리팩토링을 설명하지 않습니다. 이는 후속 테스트를 작성하는 데 더 적은 시간을 소비하는 것을 목표로하는 테스트 리팩토링에 의해 균형을 이룹니다.)

사실 후에 테스트를 작성하는 것에 대해 이야기한다면 더 많은 시간을 할애 할 것입니다.

  • 원하는 행동을 결정합니다.
  • 원하는 행동을 테스트하는 방법 결정.
  • 테스트를 작성할 수 있도록 코드 종속성을 수행합니다.
  • 실패한 테스트 코드를 수정합니다.

실제로 코드를 작성하는 데 소비하는 것보다.

그렇습니다. 예상 조치입니다.


3

나는 그것이 가장 중요한 부분이라고 생각합니다.

단위 테스트는 항상 "제대로 작동하는지 확인"에 관한 것이 아니라 학습에 관한 것입니다. 무언가를 충분히 테스트하면 두뇌에 "하드 코딩"되고 결국 단위 테스트 시간이 단축되고 완료 될 때까지 아무 것도 테스트하지 않고도 전체 클래스와 메서드를 작성할 수 있습니다.

이것이 바로이 페이지의 다른 답변 중 하나가 "코스"에서 90 % 테스트를했다고 언급 한 이유입니다.

단위 테스트는 문자 그대로 기술을 향상시키기 때문에 시간을 매우 소중하게 사용하는 것이 아니라 자신의 코드를 다시 살펴보고 그 과정에서 논리적 실수를 찾는 좋은 방법입니다.


2

많은 사람들이 사용할 수 있지만 그것은 다릅니다.

테스트를 먼저 작성하는 경우 (TDD) 테스트 작성에 소요되는 시간이 약간 중복 될 수 있으며 실제로 코드 작성에 도움이됩니다. 치다:

  • 결과 및 입력 결정 (매개 변수)
  • 명명 규칙
  • 구조-물건을 넣을 위치.
  • 평범한 옛 생각

코드를 작성한 후 테스트를 작성할 때 코드를 쉽게 테스트 할 수 없으므로 테스트 작성이 더 어렵거나 더 오래 걸립니다.

대부분의 프로그래머는 테스트보다 훨씬 긴 코드를 작성해 왔으므로 대부분 유창하지 않을 것으로 기대합니다. 또한 테스트 프레임 워크를 이해하고 활용하는 데 걸리는 시간을 추가 할 수 있습니다.

코딩하는 데 걸리는 시간과 단위 테스트가 수행되는 방식에 대한 사고 방식을 바꿔야한다고 생각합니다. 단기간에 그것을 보지 말고 특정 기능을 제공하는 데 걸리는 총 시간을 비교하지 마십시오. 더 나은 / 덜 버그가있는 코드를 작성할뿐만 아니라 변경하기 쉽고 여전히 코드를 작성해야하기 때문에 고려해야합니다. 더 좋거나 적은 버기.

어느 시점에서 우리는 모두 매우 훌륭한 코드를 작성할 수 있기 때문에 일부 도구와 기술은 기술을 향상시키는 데 많은 도움을 줄 수 있습니다. 레이저 가이드 톱만 있으면 집을 지을 수는 없습니다.


2

실제 코드보다 테스트를 작성하는 데 많은 시간을 소비하는 것이 일반적입니까?

그렇습니다. 몇 가지 경고가 있습니다.

우선, 대부분의 큰 상점은 이런 식으로 작동한다는 의미에서 "정상"입니다. 따라서이 방법이 완전히 잘못 안내되고 멍청하더라도 여전히 대부분의 큰 상점은 이런 식으로 작동한다는 사실이 "정상"입니다.

이것으로 테스트가 잘못되었다는 것을 의미하지는 않습니다. 나는 테스트가없는 환경과 강박 적 테스트가 필요한 환경에서 일했지만 강박 적 테스트조차도 테스트가없는 것보다 낫다고 말할 수 있습니다.

그리고 아직 TDD를 수행하지는 않습니다. (누군가 알고 있을지 모르지만) 실제 응용 프로그램이 아닌 테스트를 실행하여 편집 실행 디버그주기의 대부분을 수행하므로 자연스럽게 많은 작업을합니다. 가능한 한 실제 응용 프로그램을 실행하지 않아도되도록 테스트했습니다.

그러나 과도한 테스트, 특히 테스트 유지 관리 에 소요되는 시간이 위험하다는 점에 유의 하십시오. (나는 이것을 구체적으로 지적하기 위해 주로이 대답을 쓰고 있습니다.)

Roy Osherove의 단위 테스트 기술 (Manning, 2009) 의 서문 에서 저자는 잘못 설계된 단위 테스트에 의해 부과 된 엄청난 개발 부담으로 인해 상당 부분 실패한 프로젝트에 참여한 것으로 인정합니다. 개발 노력의 기간. 따라서 테스트를 유지하는 것 외에는 아무 것도하지 않고 너무 많은 시간을 소비한다고해서 반드시 "정상"이기 때문에 올바른 경로에 있다는 것을 의미하지는 않습니다. 개발 노력이 건강에 해로운 모드로 전환되었을 수 있으며, 프로젝트를 저장하기 위해 테스트 방법론의 근본적인 재고가 필요할 수 있습니다.


0

실제 코드보다 테스트를 작성하는 데 많은 시간을 소비하는 것이 일반적입니까?

  • 예를 기록하기위한 수단 - 테스트 코드 인 경우 (분리의 모듈 테스트) 고도 결합 (레거시 부족 의 분리 누락 의존성 주입을 하지 개발 TDD )
  • 테스트 할 로직이 GUI 코드 를 통해서만 도달 할 수있는 경우 통합 / 수락 테스트 작성의 경우
  • 아니 GUI를-코드와만큼 통합 / 수용-테스트를 작성하기위한 분리 비즈니스 로직 (테스트는 GUI와 상호 작용 할 필요가 없습니다)
  • 우려의 분리, 의존성 주입, 코드가 테스트 주도 개발 (tdd) 인 경우 단위 테스트 작성에 대해 아니오
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.