단위 테스트에서 임의의 데이터?


136

임의의 데이터로 필드를 채우는 객체에 대한 단위 테스트를 작성하는 동료가 있습니다. 그의 이유는 다양한 값을 테스트 할 것이기 때문에 더 넓은 범위의 테스트를 제공하는 반면, 일반 테스트는 단일 정적 값만 사용하기 때문입니다.

나는 그에 대해 여러 가지 다른 이유를주었습니다. 주된 이유는 다음과 같습니다.

  • 임의의 값은 테스트를 실제로 반복 할 수 없음을 의미합니다 (또한 테스트가 무작위로 실패 할 경우 빌드 서버에서 실패하여 빌드를 중단 할 수 있음).
  • 임의의 값이고 테스트가 실패하면 a) 객체를 수정하고 b) 매번 해당 값을 테스트하도록 강제해야하므로 작동한다는 것을 알고 있지만 임의이므로 값이 무엇인지 알 수 없습니다.

다른 동료가 추가했습니다.

  • 예외를 테스트하는 경우 임의의 값을 사용하면 테스트가 예상 상태로 끝나지 않습니다.
  • 무작위 데이터는 단위 테스트가 아닌 시스템 플러시 및로드 테스트에 사용됩니다.

다른 사람이 내가 그 일을 그만두도록 할 수있는 다른 이유를 추가 할 수 있습니까?

(또는 대안으로, 이것은 단위 테스트를 작성하는 데 허용되는 방법이며, 나와 다른 동료가 틀렸습니까?)


32
"임의의 값은 테스트가 실제로 반복 될 수 없음을 의미합니다"는 사실이 아닙니다. tets는 의사 난수를 사용하기 때문입니다. 동일한 초기 시드를 제공하고 동일한 "임의"테스트 시퀀스를 얻습니다.
Raedwald

11
일화 : 한 번은 CSV 내보내기 클래스를 작성했으며 임의의 테스트에서 제어 문자가 셀 끝에 배치 될 때 버그가 발견되었습니다. 무작위 테스트가 없다면 테스트 케이스로 추가하려고 생각하지 않았을 것입니다. 항상 실패 했습니까? 아니요. 완벽한 테스트입니까? 아니요. 버그를 파악하고 수정하는 데 도움이 되었습니까? 예.
Tyzoid

1
테스트는 코드가 입력으로 예상되는시기와 출력으로 예상되는 것을 설명하기위한 문서화 역할을 할 수도 있습니다. 임의의 데이터를 명확하게 테스트하는 것은 임의의 데이터를 생성하는 코드보다 간단하고 설명이 쉽습니다.
splintor

임의로 생성 된 값으로 인해 단위 테스트가 실패하고이 값이 어설 션의 일부가 아닌 경우 단위 테스트를 디버깅하는 것이 좋습니다.
eriksmith200

답변:


72

타협이 있습니다. 동료가 실제로 무언가에 있지만, 그가 잘못하고 있다고 생각합니다. 완전히 무작위 테스트가 매우 유용하다는 것을 확신하지는 않지만 확실히 유효하지는 않습니다.

프로그램 (또는 단위) 사양은이를 충족하는 일부 프로그램이 존재한다는 가설입니다. 프로그램 자체는 그 가설의 증거입니다. 단위 테스트는 프로그램이 사양에 따라 작동한다는 반박 증거를 제공하려는 시도입니다.

이제 단위 테스트를 직접 작성할 수 있지만 실제로는 기계적인 작업입니다. 자동화 할 수 있습니다. 스펙을 작성하기 만하면됩니다. 기계는 코드를 손상 시키려고 수많은 단위 테스트를 생성 할 수 있습니다.

사용중인 언어를 모르지만 여기를 참조하십시오.

자바 http://functionaljava.org/

스칼라 (또는 자바) http://github.com/rickynils/scalacheck

하스켈 http://www.cs.chalmers.se/~rjmh/QuickCheck/

.NET : http://blogs.msdn.com/dsyme/archive/2008/08/09/fscheck-0-2.aspx

이러한 도구는 올바른 형식의 스펙을 입력으로 사용하고 자동으로 생성 된 데이터를 사용하여 원하는만큼 단위 테스트를 자동으로 생성합니다. 그들은 "축소"전략 (비틀기 가능)을 사용하여 가능한 가장 간단한 테스트 사례를 찾아 코드를 깨뜨리고 에지 사례를 잘 커버하는지 확인합니다.

행복한 테스트!


1
+1합니다. ScalaCheck는 반복 가능한 방식으로 최소화 된 무작위 테스트 데이터를 생성하는 경이로운 작업을 수행합니다.
Daniel Spiewak

17
무작위가 아닙니다. 임의적입니다. 큰 차이 :)
Apocalisp

reductiotest.org는 이제 더 이상 존재하는 것으로 보이며 Google은 다른 곳을 알려주지 않았습니다. 지금 어디에 있는지 아십니까?
Raedwald

이제 기능적 Java 라이브러리의 일부입니다. 링크가 수정되었습니다. 그러나 Scalacheck를 사용하여 Java 코드를 테스트합니다.
Apocalisp

ScalaCheck가 GitHub로 이전했습니다. 답변의 링크가 업데이트되었습니다. 스칼라뿐만 아니라 Java에도 유용합니다. (이전 링크는 code.google.com/p/scalacheck )
RobertB

38

이런 종류의 테스트를 원숭이 테스트 라고합니다 . 올바르게 수행하면 정말 어두운 구석에서 벌레를 피울 수 있습니다.

재현성에 대한 귀하의 우려를 해결하기 위해 : 이것에 접근하는 올바른 방법은 실패한 테스트 항목을 기록하고 단위 테스트를 생성 하여 특정 버그 의 전체 제품군 을 조사하는 것입니다. 초기 테스트 실패를 야기한 (임의 데이터로부터의) 하나의 특정 입력을 유닛 테스트에 포함시킨다.


26

PRNG를 일정하게 시드하는 용도로 사용되는 중간 집이 있습니다. 이를 통해 반복 가능한 '무작위'데이터를 생성 할 수 있습니다.

개인적으로 나는 (일정한) 무작위 데이터가 테스트에 유용한 곳이 있다고 생각합니다. PRNG의 자극을 사용하여 신중하게 생각한 모든 구석을 다했다고 생각한 후에는 때때로 다른 것을 찾을 수 있습니다.


4
나는 많은 잠금과 스레드가있는 시스템 에서이 작업을 잘 보았습니다. '랜덤'시드는 각 실행에서 파일에 기록 된 다음 실행이 실패한 경우 코드가 취한 경로를 해결하고 우리가 놓친 경우를 위해 손으로 쓴 단위 테스트를 작성할 수 있습니다.
Ian Ringrose

PRNG는 무엇을 의미합니까?
systemovich

의사 난수 생성기
Will Dean

16

Beautiful Code 책 에는 "Beautiful Tests"라는 장이 있는데, 여기서 Binary Search 알고리즘에 대한 테스트 전략을 진행 합니다. 한 단락을 "임의 테스트 행위"라고하며, 여기서 알고리즘을 철저히 테스트하기 위해 임의의 배열을 만듭니다. 이 책 중 일부를 온라인으로 읽을 수 있습니다 ( 95 페이지 Google 도서) . 그러나 그만한 가치가있는 책입니다.

따라서 기본적으로 이것은 테스트를 위해 임의의 데이터를 생성하는 것이 가능한 옵션임을 보여줍니다.


16

나는 무작위 테스트에 찬성하여 작성합니다. 그러나 특정 빌드 환경에 적합한 지 여부와 포함해야 할 테스트 스위트가 더 미묘한 문제입니다.

무작위 테스트를 통해 로컬에서 (예 : 개발자 박스에서 밤새) 실행하면 명백하고 모호한 버그가 발견되었습니다. 모호한 테스트는 무작위 테스트로 실제로 테스트 할 수있는 유일한 현실적인 테스트라고 생각합니다. 테스트로, 무작위 테스트를 통해 발견 된 찾기 힘든 버그를 하나 발견했으며, 개발자가 약 12 ​​줄의 코드 (약 12 줄의 코드)를 검토하도록했습니다. 아무도 그것을 감지하지 못했습니다.

무작위 데이터에 대한 많은 주장은 "테스트를 재현 할 수 없습니다"라는 풍미입니다. 그러나 잘 작성된 무작위 테스트는 무작위 시드를 시작하고 실패시 출력하는 데 사용되는 시드를 캡처합니다. 직접 테스트를 반복 할 수있을뿐만 아니라, 해당 테스트의 시드를 하드 코딩하여 특정 문제를 테스트하는 새로운 테스트를 간단하게 만들 수 있습니다. 물론,이 경우를 다루는 명시 적 테스트를 직접 코딩하는 것이 더 좋지만 게으름에는 장점이 있으며, 따라서 실패한 시드에서 새로운 테스트 사례를 자동 생성 할 수도 있습니다.

그러나 내가 토론 할 수 없다는 점은 빌드 시스템을 손상 시킨다는 것입니다. 대부분의 빌드 및 연속 통합 테스트는 매번 테스트가 동일한 작업을 수행 할 것으로 예상합니다. 따라서 무작위로 실패한 테스트는 혼란을 일으키고 무작위로 실패하고 무해한 변화를 손가락으로 가리킬 것입니다.

해결책은 빌드 및 CI 테스트의 일부로 무작위 테스트를 계속 실행하지만 고정 된 수의 반복을 위해 고정 시드로 실행하는 것입니다 . 따라서 테스트는 항상 동일한 작업을 수행하지만 여러 반복을 위해 실행하는 경우 여전히 많은 입력 공간을 탐색합니다.

예를 들어 관련 클래스를 변경할 때 로컬로 더 많은 반복 또는 다른 시드를 위해 자유롭게 실행할 수 있습니다. 무작위 테스트가 점점 더 대중화되면 무작위로 알려진 특정 테스트 세트를 상상할 수 있습니다.이 테스트는 다른 시드로 실행될 수 있으며 (따라서 시간이 지남에 따라 적용 범위가 증가 함) 실패가 동일한 것을 의미하지 않는 경우 결정적 CI 시스템으로서 (즉, 실행은 코드 변경과 1 : 1과 관련이 없으므로 실패 할 때 특정 변경을 손가락으로 가리 키지 않습니다).

무작위 시험, 특히 잘 작성된 시험에 대해 많은 이야기가 있으므로 너무 빨리 끝내지 마십시오!


14

TDD를하고 있다면 임의의 데이터가 훌륭한 접근법이라고 주장합니다. 테스트가 상수로 작성된 경우 코드가 특정 값에 대해서만 작동한다고 보장 할 수 있습니다. 테스트가 빌드 서버에 무작위로 실패하면 테스트 작성 방법에 문제가있을 수 있습니다.

무작위 데이터는 향후 리팩토링이 마법 상수에 의존하지 않도록 보장합니다. 결국, 테스트가 문서 인 경우 상수가 있다는 것이 해당 상수에 대해서만 작동해야 함을 의미하지 않습니까?

나는 과장하고 있지만 "이 변수의 값이이 테스트의 결과에 영향을 미치지 않아야한다"는 표시로 임의의 데이터를 테스트에 주입하는 것을 선호한다.

임의 변수를 사용하면 해당 변수를 기반으로 테스트를 포크하면 냄새입니다.


10

테스트를 보는 누군가에게 한 가지 장점은 임의의 데이터가 명확하지 않다는 것입니다. 수십 개의 데이터를 포함하는 테스트가 너무 많았으며 그 방법이 무엇인지, 그리고 그 방법이 무엇인지 알기가 어려울 수 있습니다. 예를 들어 주소 유효성 검사 방법이 특정 우편 번호로 테스트되고 다른 모든 데이터가 무작위 인 경우 우편 번호가 유일한 중요한 부분임을 확신 할 수 있습니다.


9
  • 임의의 값이고 테스트가 실패하면 a) 객체를 수정하고 b) 매번 해당 값을 테스트하도록 강제해야하므로 작동한다는 것을 알고 있지만 임의이므로 값이 무엇인지 알 수 없습니다.

테스트 케이스에 테스트 대상을 정확하게 기록하지 않으면 테스트 케이스를 다시 코딩해야합니다. 나는 항상 테스트 사례에 대해 다시 참조 할 수있는 로그를 가지고 있기 때문에 정적 데이터 또는 임의 데이터를 사용하는지 여부에 무엇이 실패했는지 정확하게 알 수 있습니다.


9

동료 는 잘 모르지만 퍼즈 테스트 를하고 있습니다. 서버 시스템에서 특히 유용합니다.


2
그러나 이것이 단위 테스트와 근본적으로 다른 것이 아닌가? 다른 시간에 끝났습니까?
endolith

1
@endolith 특정 시간에 특정 테스트를 실행하도록 강요하는 물리 법칙은 없습니다
user253751

1
@immibis 그러나 특정 시간에 특정 테스트를 수행해야하는 좋은 이유가 있습니다. 사용자가 "확인"버튼을 클릭 할 때마다 단위 테스트 배터리를 실행하지 않습니다.
endolith

5

임의의 데이터를 한 번만 생성 할 수 있습니까 (테스트 실행 당 한 번이 아니라 정확히 한 번 의미 함) 이후 모든 테스트에서 사용할 수 있습니까?

나는 당신이 생각하지 않은 경우를 테스트하기 위해 임의의 데이터를 만드는 것의 가치를 확실히 알 수 있지만, 무작위로 통과하거나 실패 할 수있는 단위 테스트를 갖는 것은 좋지 않습니다.


5

시험의 목표가 무엇인지 스스로에게 물어봐야합니다.
단위 테스트 는 논리, 코드 흐름 및 객체 상호 작용을 확인하는 것입니다. 임의의 값을 사용하면 다른 목표를 달성하려고하므로 테스트 초점과 단순성이 줄어 듭니다. 가독성을 위해 허용됩니다 (UUID, ID, 키 생성 등).
특히 단위 테스트의 경우,이 방법으로 문제를 발견 한 후에도 회상 할 수 없습니다. 그러나 나는 많은 결정 론적 문제 (테스트에서)가 임의의 값과 주로 임의의 날짜로 영리하려고 노력하는 것을 보았습니다.
퍼지 테스트는 통합 테스트엔드 투 엔드 테스트에 대한 올바른 접근 방식입니다 .


퍼지에 임의의 입력을 사용하는 것이 가능할 때 적용 범위 안내 퍼지를 대체하는 것은 아니라고 덧붙입니다.
gobenji

1

테스트에 임의의 입력을 사용하는 경우 입력 값을 기록하여 값이 무엇인지 확인할 수 있습니다. 이런 식으로 우연히 만나는 경우가 있습니다. 그것을 재현하는 테스트를 작성. 사람들이 임의의 입력을 사용하지 않는다는 동일한 이유를 들었지만 특정 테스트 실행에 사용되는 실제 값에 대한 통찰력이 있으면 큰 문제가되지 않습니다.

"임의"데이터 개념은 중요 하지 않은 것을 의미하는 방법으로도 매우 유용합니다 . 현재 테스트와 관련이없는 많은 노이즈 데이터가있는 곳을 염두에 두는 수용 테스트가 있습니다.


0

객체 / 앱에 따라 임의의 데이터가로드 테스트에 사용될 수 있습니다. 데이터의 경계 조건을 명시 적으로 테스트하는 데이터를 사용하는 것이 더 중요하다고 생각합니다.


0

우리는 오늘 이것에 부딪쳤다. 나는 의사 난수를 원 했습니다 (따라서 크기면에서 압축 된 오디오 데이터처럼 보일 것입니다). 나는 또한 싶다고 TODO'd 결정 . rand ()는 Linux와 OSX에서 다릅니다. 다시 시드하지 않으면 언제든지 바뀔 수 있습니다. 따라서 결정적이지만 여전히 의사 난수로 변경했습니다. 미리 준비된 데이터 (보다 편리하게 작성)를 사용하는 것만 큼 테스트를 반복 할 수 있습니다.

이것은 코드 경로를 통한 임의의 무차별 강제 테스트 는 아닙니다 . 차이점은 여전히 ​​결정 론적이며 여전히 반복적이며 복잡한 논리에서 엣지 케이스에 대한 흥미로운 검사를 실행하기 위해 실제 입력처럼 보이는 데이터를 사용하는 것입니다. 여전히 단위 테스트.

그래도 자격이 무작위입니까? 맥주에 대해 이야기합시다. :-)


0

테스트 데이터 문제에 대한 세 가지 솔루션을 상상할 수 있습니다.

  • 고정 데이터로 테스트
  • 무작위 데이터로 테스트
  • 임의의 데이터를 한 번 생성 다음 고정 데이터로 사용하십시오.

위의 모든 작업을 수행하는 것이 좋습니다 . 즉, 뇌를 사용하여 해결 된 일부 엣지 사례와 한 번만 생성하는 무작위 데이터를 사용하여 반복 가능한 단위 테스트를 작성하십시오. 당신이 실행하는 것이 그 다음 무작위 시험의 집합을 쓰기 .

무작위 테스트는 반복 가능한 테스트에서 놓친 부분을 포착하지 않아야합니다. 반복 가능한 테스트로 모든 것을 다루고 무작위 테스트는 보너스로 간주해야합니다. 그들이 무언가를 찾으면, 그것은 당신이 합리적으로 예측할 수 없었던 것이어야합니다. 진짜 괴짜.


-2

시험이 수정되었는지 확인하지 못한 경우 어떻게 시험을 다시 실행할 수 있습니까? 즉, 테스트의 반복성을 잃습니다.

다른 응답에서 언급했듯이 테스트에서 임의의 데이터를로드하는 데 약간의 가치가 있다고 생각하지만 다른 것보다로드 테스트라는 제목 아래에 더 많이 속합니다. 그것은 거의 "희망 테스트"연습입니다. 실제로, 당신의 남자는 단순히 자신이 테스트하려고하는 것에 대해 생각하지 않으며, 무작위성을 기대함으로써 생각의 부족을 보충하는 것은 결국 신비한 오류를 가두 게 될 것이라고 생각합니다.

제가 그와 함께 사용할 논쟁은 그가 게으르다는 것입니다. 또는 다른 방법으로, 테스트하려는 것을 이해하는 데 시간이 걸리지 않으면 작성중인 코드를 실제로 이해하지 못했을 수 있습니다.


3
테스트를 재현 할 수 있도록 랜덤 데이터 또는 랜덤 시드를 기록 할 수 있습니다.
cbp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.