"좋은"단위 테스트를 작성하는 방법?


61

이 스레드에 의해 트리거 되어 내 프로젝트에서 최종적으로 단위 테스트를 사용하려고 생각합니다. 몇몇 포스터는 "테스트가 훌륭하면 테스트가 훌륭합니다"와 같은 것을 말합니다. 지금 내 질문 : "좋은"테스트 란 무엇입니까?

내 응용 프로그램에서 주요 부분은 많은 양의 관측 데이터에 따라 일종의 수치 분석이며 종종이 데이터를 모델링하는 데 사용할 수있는 적합 함수를 생성합니다. 가능한 입력 및 결과의 수가 너무 많아서 모든 경우를 테스트하기에는 너무 크기 때문에 메소드 자체는 종종 길고 성능을 저하시키지 않고 쉽게 리팩토링 할 수 없기 때문에 이러한 메소드에 대한 테스트를 구성하기가 특히 어렵다는 것을 알았습니다. 특히 이런 종류의 방법에 대한 "좋은"테스트에 관심이 있습니다.


8
좋은 단위 테스트는 한 가지만 테스트해야합니다. 실패하면 정확히 무엇이 잘못되었는지 알아야합니다.
gablin

2
많은 양의 데이터가있는 경우 데이터 파일을 입력으로 사용할 수있는 일반 테스트를 작성하는 것이 좋습니다. 데이터 파일에는 일반적으로 입력 및 예상 결과가 모두 포함되어야합니다. xunit 테스트 프레임 워크를 사용하면 각 데이터 샘플마다 하나씩 테스트 사례를 즉시 생성 할 수 있습니다.
froderik

2
@gablin "실패하면 정확히 무엇이 잘못되었는지 알아야합니다."는 테스트 결과에서 원인을 파악할 수있는 한 여러 가지 가능한 실패 원인이있는 테스트가 정상임을 나타냅니다.
user253751 2018 년

단위 테스트로 작업 시간을 테스트 할 수 있다고 언급 한 사람은 없습니다. 성능을 염두에두고 코드를 리팩터링하여 단위 테스트가 시간과 결과에 따라 통과하는지 여부를 알려줍니다.
CJ Dennis

답변:


52

단위 테스트 기술은 단위 테스트 에 대해 다음과 같이 말합니다.

단위 테스트에는 다음과 같은 속성이 있어야합니다.

  • 자동화되고 반복 가능해야합니다.
  • 구현하기 쉬워야합니다.
  • 작성된 후에는 나중에 사용할 수 있도록 남겨 두어야합니다.
  • 누구나 실행할 수 있어야합니다.
  • 버튼을 누르면 실행됩니다.
  • 빨리 실행되어야합니다.

나중에 완전히 자동화되고 신뢰할 수 있고 읽기 쉽고 유지 관리가 가능해야한다고 덧붙입니다.

이 책을 아직 읽지 않았다면이 책을 읽는 것이 좋습니다.

내 의견으로는,이 모든 것이 매우 중요하지만 마지막 세 가지 (신뢰할 수 있고 읽기 쉽고 유지 관리 가능)는 특히 테스트에 이러한 세 가지 속성이있는 것처럼 코드에 일반적으로 있습니다.


1
단위 테스트 (통합 또는 기능 테스트 아님)를 대상으로하는 포괄적 인 목록을 보려면 +1
Gary Rowe

1
링크의 경우 +1 흥미로운 자료가 있습니다.
Joris Meys

1
"빠르게 실행"에는 큰 의미가 있습니다. 단위 테스트가 데이터베이스, 파일 시스템, 웹 서비스 등과 같은 외부 리소스와 분리되어 독립적으로 실행되어야하는 한 가지 이유입니다. 결과적으로 모의 / 스텁이 발생합니다.
Michael Easter

1
그것이 말할 때 It should run at the push of a button, 단위 테스트는 (테스트중인 단위에 대해) 컨테이너 (앱 서버)를 실행하거나 리소스 연결 (예 : DB, 외부 웹 서비스 등)을 요구하지 않아야합니까? 응용 프로그램의 어느 부분을 단위 테스트해야하고 어떤 부분을 테스트해서는 안되는지 혼란 스럽습니다. 단위 테스트는 DB 연결 및 컨테이너 실행에 의존해서는 안되며 대신 모형을 사용해야한다고 들었습니다.
양서류

42

좋은 단위 테스트는 테스트하는 기능을 반영하지 않습니다.

크게 단순화 된 예로서, 평균 2 int를 리턴하는 함수가 있다고 가정하십시오. 가장 포괄적 인 테스트는 함수를 호출하고 결과가 실제로 평균인지 확인합니다. 이것은 전혀 의미가 없습니다. 테스트하고있는 기능을 미러링 (복제)하고 있습니다. 주 기능에서 실수를 한 경우 테스트에서 같은 실수를합니다.

다시 말해, 단위 테스트에서 주요 기능을 복제 한 경우 시간을 낭비하고 있다는 신호일 수 있습니다.


21
+1이 경우 하드 코딩 된 인수로 테스트하고 알려진 답변을 확인하십시오.
Michael K

나는 전에 그 냄새를 보았다.
Paul Butcher

평균을 반환하는 함수에 대한 좋은 단위 테스트의 예를 들어 주시겠습니까?
VLAS

2
@VLAS 사전 정의 값, 예를 들어 avg (1, 3) == 2를 확인하고 INT_MAX, 0, 음수 값 등과 같은 엣지 케이스를 더 중요하게 확인하십시오. 버그가 발견되어 함수에서 수정 된 경우 다른 값을 추가하십시오. 이 버그가 다시 소개되지 않도록 테스트하십시오.
mojuba

흥미 롭군 테스트 입력에 대한 정답을 얻는 방법을 제안하고 테스트 대상 코드와 같은 실수를하지 않을 수 있습니까?
Timo

10

좋은 단위 테스트는 본질적으로 실행 가능한 형식의 사양입니다.

  1. 사용 사례에 해당하는 코드의 동작 설명
  2. 기술적 인 코너 사례를 다루는 경우 (null이 전달되는 경우 발생)-코너 사례에 대한 테스트가 없으면 동작이 정의되지 않습니다.
  3. 테스트 된 코드가 사양에서 변경되면 중단

필자는 API를 먼저 작성하고 실제 구현을 테스트 할 때 Test-Driven-Development가 라이브러리 루틴에 매우 적합하다는 것을 알았습니다.


7

TDD의 경우 "좋은"테스트 는 고객이 원하는 테스트 기능을 테스트 합니다 . 기능이 반드시 기능에 해당하는 것은 아니며 개발자가 진공 상태에서 테스트 시나리오를 작성해서는 안됩니다.

귀하의 경우-추측하고 있습니다- '기능'은 fit 함수가 특정 오류 허용 오차 내에서 입력 데이터를 모델링한다는 것입니다. 나는 당신이 실제로 무엇을하고 있는지 전혀 모르기 때문에 무언가를 만들고 있습니다. 잘만되면 그것은 analgous이다.

이야기 예 :

[X-Wing Pilot]으로서 [0.0001 % 이하의 맞춤 오차]를 원하지 않아 [대상 캐년을 통해 최고 속도로 이동할 때 대상 컴퓨터가 데스 스타의 배기 포트에 닿을 수 있음]

따라서 조종사 (및 경우에 따라 대상 컴퓨터)와 대화하십시오. 먼저 '정상적인 것'에 대해 이야기하고 비정상에 대해 이야기하십시오. 이 시나리오에서 실제로 중요한 것, 일반적인 것, 가능성이없는 것 및 가능한 것만 알아냅니다.

일반적으로 속도, 피치, 롤, 요, 목표 벡터, 목표 크기 및 목표 속도의 7 가지 원격 측정 데이터 채널에 대해 0.5 초의 기간이 있으며이 값은 일정하거나 선형으로 변한다고 가정합니다. 비정상적으로 채널 수가 적거나 값이 빠르게 변경 될 수 있습니다. 따라서 함께 다음과 같은 몇 가지 테스트를 수행합니다.

//Scenario 1 - can you hit the side of a barn?
Given:
    all 7 channels with no dropouts for the full half-second window,
When:
    speed is zero
    and target velocity is zero
    and all other values are constant,
Then:
    the error coefficient must be zero

//Scenario 2 - can you hit a turtle?
Given:
    all 7 channels with no dropouts for the full half-second window,
When:
    speed is zero
    and target velocity is less than c
    and all other values are constant,
Then:
    the error coefficient must be less than 0.0000000001/ns

...

//Scenario 42 - death blossom
Given:
    all 7 channels with 30% dropout and a 0.05 second sampling window
When:
    speed is zero
    and position is within enemy cluster
    and all targets are stationary
Then:
    the error coefficient must be less than 0.000001/ns for each target

이제 이야기에 설명 된 특정 상황에 대한 시나리오가 없음을 알 수 있습니다. 고객 및 다른 이해 관계자와 이야기를 나눈 후, 원래 이야기의 목표는 단지 ​​가상의 예일뿐입니다. 실제 테스트는 다음 논의에서 나왔습니다. 이런 일이 일어날 수 있습니다. 스토리를 다시 작성해야하지만 스토리는 고객과의 대화를위한 자리 표시 자이므로 반드시 수행 할 필요는 없습니다.


5

최소 입력 수 (1 또는 0 가능)와 몇 가지 표준 사례 만 포함 된 테스트 세트와 같이 코너 사례에 대한 테스트를 작성하십시오. 이러한 단위 테스트는 철저한 승인 테스트를 대체하지 않으며 그렇지 않습니다.


5

사람들이 거의 입력하지 않는 코드에 대한 테스트를 작성하고 자주 입력하는 코드에 대한 테스트를 작성하지 않는 데 많은 노력을 기울이는 경우가 많이있었습니다.

테스트를 작성하기 위해 앉아 있기 전에 적절한 범위를 계획 할 수 있도록 일종의 콜 그래프를보고 있어야합니다.

또한 나는 "그래, 우리는 그것을 테스트한다"고 말하는 테스트를 믿지 않는다. 내가 떨어졌고 불변의 라이브러리를 사용한다면, 테스트를 작성하는 데 하루를 낭비하지 않고 특정 부분이 점수를 매기는 경우에도 변경되지 않는 API 내부가 예상대로 작동하는지 확인합니다. 통화 그래프에서 높음. 해당 라이브러리 (내 코드) 를 소비하는 테스트가 이것을 지적합니다.


그러나 나중에 라이브러리에 버그 수정이 포함 된 최신 버전이 있으면 어떻게됩니까?

@ Thorbjørn Ravn Andersen-라이브러리, 변경된 사항 및 자체 테스트 프로세스에 따라 다릅니다. 나는 그것을 제자리에 떨어 뜨렸을 때 작동한다고 알고있는 코드에 대한 테스트를 작성하지 않을 것이며 절대 만지지 마십시오. 따라서 업데이트 후에 작동하면 마음에 들지 않습니다.) 물론 예외가 있습니다.
Tim Post

라이브러리에 의존하는 경우 최소한 라이브러리에서 실제로 수행 할 작업 을 보여주는 테스트를 작성하는 것이 가장 좋습니다 .

... 그리고 그것이 바뀌면, 상기 라이브러리를 소비하는 것들에 대한 테스트 ... tl; dr; 타사 코드의 내부를 테스트 할 필요가 없습니다. 그러나 명확성을 위해 답변이 업데이트되었습니다.
Tim Post

4

TDD는 아니지만 QA에 들어간 후 QA 프로세스 중에 발생하는 버그를 재현하도록 테스트 케이스를 설정하여 테스트를 개선 할 수 있습니다. 이것은 장기적인 지원을받을 때 사람들이 부주의하게 오래된 버그를 재 도입 할 위험에 처할 때 특히 유용 할 수 있습니다. 특히 귀중한 정보를 포착하기 위해 테스트를 실시합니다.


3

모든 테스트가 한 가지만 테스트하도록 노력합니다. 각 테스트에 shouldDoSomething ()과 같은 이름을 지정하려고합니다. 구현이 아닌 동작을 테스트하려고합니다. 나는 공개 방법 만 테스트합니다.

나는 일반적으로 성공을위한 하나 또는 몇 가지 테스트를 수행 한 다음 공개 방법에 따라 실패에 대한 테스트를 수행 할 수 있습니다.

나는 모형을 많이 사용합니다. PowerMock과 같은 훌륭한 모의 프레임 워크가 도움이 될 것입니다. 아직 사용하지는 않지만

클래스 A가 다른 클래스 B를 사용하는 경우 A가 B를 직접 사용하지 않도록 인터페이스 X를 추가합니다. 그런 다음 모형 XMockup을 만들어 테스트 대신 B 대신 사용합니다. 실제로 테스트 실행 속도를 높이고 테스트 복잡성을 줄이며 B의 특성에 대처할 필요가 없으므로 A에 대해 작성하는 테스트 수를 줄일 수 있습니다. 예를 들어 A가 X.someMethod ()를 호출하는지 테스트 할 수 있습니다 B.someMethod () 호출의 부작용 대신.

테스트 코드도 깨끗하게 유지하십시오.

데이터베이스 계층과 같은 API를 사용할 때 그것을 조롱하고 모형이 명령에 대한 가능한 모든 기회에서 예외를 던질 수 있도록합니다. 그런 다음 테스트가 다시 실패 할 때까지 다음 기회에 예외를 던질 때마다 던지지 않고 테스트를 실행합니다. Symbian에 사용 가능한 메모리 테스트와 비슷합니다.


2

Andry Lowry가 이미 Roy Osherove의 단위 테스트 측정 항목을 게시 한 것으로 보입니다. 그러나 밥 삼촌이 Clean Code (132-133) 에서 제공하는 (무료) 세트를 제시 한 사람은 아무도없는 것 같습니다 . 그는 약어 FIRST를 사용합니다 (여기서 나의 요약과 함께).

  • 빨리 (빨리 달려야하므로 사람들은 달리지 않아도됩니다)
  • 독립적 (테스트는 서로 설정하거나 해제하지 않아야 함)
  • 반복 가능 (모든 환경 / 플랫폼에서 실행해야 함)
  • 자체 유효성 검사 (완전 자동화, 출력은 로그 파일이 아니라 "통과"또는 "실패"여야 함)
  • 적시 (작성할 때 — 생산 코드를 작성하기 직전에 테스트)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.