단위 테스트 Proof By Example을 수동으로 작성합니까?


9

JUnit 테스트 작성은 코드를 통한 특정 경로를 보여줍니다.

내 동료 중 하나가 다음과 같이 댓글을 달았습니다.

단위 테스트를 수동으로 작성하는 것은 Proof By Example 입니다.

그는 Quickcheck 와 같은 툴 과 타입으로 프로그램 동작추론 할 수있는 능력을 가진 Haskell의 배경에서왔다 .

그의 의미는 코드가 테스트되지 않은이 방법으로 시도되지 않은 많은 다른 입력 조합이 있다는 것입니다.

내 질문은 : 수동으로 단위 테스트를 작성하고 있습니까?


3
아니요, 테스트를 쓰거나 사용 하지 않습니다 . 단위 테스트가 프로그램에 아무런 문제가 없음을 증명한다고 주장 하는 것은 Proof by Example (부적절한 일반화)입니다. 테스트는 수학적으로 코드 정확성을 입증하는 것이 아닙니다. 테스트는 본질적으로 실험적인 검사입니다. 코드에 대해 말함으로써 자신감을 키우는 데 도움이되는 안전망입니다. 그러나 코드를 조사하기 위해 좋은 전략을 선택해야하는 사람이고 해당 데이터의 의미를 해석해야하는 사람입니다.
Filip Milovanović '12

답변:


10

테스트를 위해 무작위로 입력을 선택하는 경우 Proof By Example 논리 오류가 발생했을 수 있습니다.

그러나 좋은 단위 테스트는 결코 그렇게하지 않습니다. 대신, 그들은 범위가장자리 사례를 다룹니다.

예를 들어 정수를 입력으로 받아들이는 절대 값 함수에 대한 단위 테스트를 작성하는 경우 코드가 작동하는지 증명하기 위해 가능한 모든 입력 값을 테스트 할 필요는 없습니다. 종합적인 테스트를 수행하려면 -1, 0, 1 및 입력 정수의 최대 값과 최소값 만 5 개만 필요합니다.

이 5 개의 값은 가능한 모든 범위와 함수의 경우를 테스트합니다. 함수가 모든 입력 값에 대해 작동하는 높은 신뢰 수준을 얻기 위해 가능한 다른 모든 입력 값 (즉, 정수 유형이 나타낼 수있는 모든 숫자)을 테스트 할 필요는 없습니다.


11
코드 테스터가 바에 들어가 맥주를 주문합니다. 5 맥주. 맥주 -1 개, 맥주 MAX_VALUE 개, 치킨 null
Neil

2
"5 값"은 순수한 의미가 없습니다. 과 같은 사소한 기능을 고려하십시오 int foo(int x) { return 1234/(x - 100); }. 또한 (테스트하는 대상에 따라) 유효하지 않은 ( "범위를 벗어난") 입력이 올바른 결과를 반환하는지 확인해야 할 수도 있습니다 (예 :``find_thing (thing)``은 어떤 종류의 "찾을 수 없음"상태를 반환 함을 유의하십시오. 찾을 수없는 경우).
Brendan

3
@ 브레 단 (Brendan) : 5 가지 가치가 있다는 것은 중요하지 않습니다. 내 예제에서는 5 개의 값이됩니다. 다른 함수를 테스트하기 때문에 예제의 테스트 수가 다릅니다. 모든 기능에 정확히 5 개의 테스트가 필요하다는 말은 아닙니다. 당신은 내 대답을 읽는 것을 유추했습니다.
Robert Harvey

1
생성 테스트 라이브러리는 일반적으로 사용자보다 엣지 케이스를 테스트하는 것이 좋습니다. 예를 들어, 대신 정수의 수레를 사용하고, 경우, 라이브러리도 확인할 것 -Inf, Inf, NaN, 1e-100, -1e-100, -0, 2e200... 차라리 모두 수동으로 이러한 작업을 수행 할 필요가 없습니다 것입니다.
Hovercouch

@ 호버 쿠치 : 좋은 것을 알고 있다면 그것에 대해 듣고 싶습니다. 내가 본 가장 좋은 것은 Pex였습니다. 그러나 그것은 매우 불안정했습니다. 여기서는 비교적 간단한 기능에 대해 이야기하고 있습니다. 실제 비즈니스 로직과 같은 것을 처리 할 때 상황이 더 어려워집니다.
Robert Harvey

8

모든 소프트웨어 테스트는 "Proof By Example"과 유사하며 JUnit과 같은 도구를 사용한 단위 테스트 만이 아닙니다. 그리고 그것은 새로운 지혜가 아닙니다. 1960 년 Dijkstra 의 인용문이 있습니다 .

"테스트는 버그가 아닌 존재를 보여줍니다"

( "shows"라는 단어를 "proofs"로 바꾸십시오). 그러나 이는 임의의 테스트 데이터를 생성하는 도구의 경우에도 마찬가지입니다. 실제 함수에 대한 가능한 입력 수는 일반적으로 해당 사례를 생성하는 방법과 관계없이 우주 시대 내에 예상되는 결과에 대해 생성하고 확인할 수있는 테스트 사례 수보다 몇 배나 더 큰 숫자입니다. 많은 테스트 데이터를 생성하기 위해 생성기 도구를 사용하더라도 특정 버그를 감지 할 수있는 하나의 테스트 사례를 놓치지 않을 것이라는 보장은 없습니다.

무작위 테스트는 때때로 수동으로 생성 된 테스트 사례에서 간과 한 버그를 드러 낼 수 있습니다 . 그러나 일반적으로 테스트 할 함수에 대해 테스트를 신중하게 작성하고 가능한 한 적은 테스트 사례로 전체 코드 및 분기 적용 범위를 확보하는 것이 더 효율적입니다. 때로는 수동 테스트와 무작위 생성 테스트를 결합하는 것이 가능한 전략 일 수 있습니다. 또한 무작위 테스트를 사용할 때 재현 가능한 방식으로 결과를 얻기 위해주의를 기울여야합니다.

따라서 수동으로 생성 된 테스트는 무작위로 생성 된 테스트보다 나쁘지 않으며 종종 반대입니다.


1
임의 검사를 사용하는 모든 실제 테스트 스위트에는 단위 테스트가 있습니다. (기술적으로 단위 테스트는 무작위 테스트의 변형 된 사례 일뿐입니다.) 귀하의 말에 따르면 무작위 테스트를 수행하기가 어렵거나 무작위 테스트와 단위 테스트를 결합하는 것이 어렵다고 제안합니다. 일반적으로 그렇지 않습니다. 내 생각에, 무작위 테스트의 가장 큰 장점 중 하나는 테스트를 항상 유지하려는 코드의 속성으로 작성하는 것이 좋습니다. 포인트 테스트를 유추하는 것보다 이러한 속성을 명시 적으로 명시하고 확인했습니다!
데릭 엘 킨스

@DerekElkins : "어려운"이라는 용어는 잘못된 용어입니다. 무작위 테스트에는 약간의 노력이 필요하며 이는 수작업 테스트에 사용할 수있는 시간을 줄이는 노력입니다 (문제에 언급 된 것과 같은 슬로건을 따르는 사람들이있는 경우에는 전혀 수작업을하지 않을 것입니다). 코드 조각에 많은 무작위 테스트 데이터를 던지는 것은 작업의 절반에 지나지 않으며 각 테스트 입력에 대해 예상되는 결과를 생성해야합니다. 일부 시나리오의 경우이 작업이 자동으로 수행 될 수 있습니다. 다른 사람들에게는 그렇지 않습니다.
Doc Brown

좋은 배포판을 고르기 위해 어떤 생각이 필요할 때가 있지만, 이것은 일반적으로 주요한 중단이 아닙니다. 당신의 의견은 당신이 이것에 대해 잘못 생각하고 있다고 제안합니다. 무작위 검사를 위해 작성하는 특성은 모델 검사 또는 공식 증거를 위해 작성하는 특성과 동일합니다. 실제로, 그것들은 동시에 모든 것들에 사용될 수 있고 사용되었습니다. 생성해야 할 "예상 결과"가 없습니다. 대신, 항상 유지해야하는 속성을 명시하면됩니다. 몇 가지 예 : 1) 스택에 무언가를 밀어 넣고 ...
Derek Elkins가 SE

... 그리고 터지는 것은 아무것도하지 않는 것과 같아야합니다. 2) 잔액이 $ 10,000보다 큰 고객은 고액 이자율을 받아야합니다. 3) 스프라이트의 위치는 항상 화면의 경계 상자 내에 있습니다. 일부 속성 은 포인트 테스트 (예 : "잔액이 $ 0 인 경우 제로 밸런스 경고 제공")에 해당 할 수 있습니다. 속성은 전체 사양을 얻는 데 이상적인 부분 사양입니다. 이러한 속성을 생각하기가 어렵다는 것은 사양이 무엇인지 확실하지 않으며 종종 좋은 단위 테스트를 생각하기가 어렵다는 것을 의미합니다.
Derek Elkins가 SE

0

테스트를 수동으로 작성하는 것은 "예제로 증명됩니다". 그러나 QuickCheck 및 제한된 범위의 유형 시스템도 마찬가지입니다. 간단한 공식 검증이 아닌 것은 코드에 대해 알려주는 내용에 제한이 있습니다. 대신, 당신은 접근의 상대적 장점에 대해 생각해야합니다.

QuickCheck와 같은 생성 테스트는 넓은 입력 공간을 청소하는 데 정말 좋습니다. 또한 수동 테스트보다 최첨단 사례를 처리하는 것이 훨씬 낫습니다. 생성 테스트 라이브러리는 현재보다 더 많이 경험할 것입니다. 반면에, 그들은 특정 출력이 아닌 불변에 대해서만 알려줍니다. 따라서 프로그램의 결과가 올바른지 확인하려면 실제로이를 확인하기위한 몇 가지 수동 테스트가 필요합니다 foo(bar) = baz.

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