어설 션 또는 단위 테스트가 더 중요합니까?


51

어설 션과 단위 테스트는 모두 코드베이스에 대한 문서 및 버그 발견 수단으로 사용됩니다. 주요 차이점은 단정 검사는 기능 검사로 기능하고 실제 입력을 보는 반면 단위 테스트는 특정 시뮬레이션 된 입력에서 실행되며 잘 정의 된 단일 "정답"에 대한 테스트입니다. 정확성을 검증하는 주요 수단으로 어설트 대 유닛 테스트를 사용하는 상대적인 장점은 무엇입니까? 어느 쪽이 더 강조되어야한다고 생각하십니까?


4
저는이 아이디어를 너무 좋아해서 소프트웨어 테스트 및 품질 보증 과정의 과제를 주제로하고 있습니다. :-)
Macneil

또 다른 질문은 다음과 같습니다. 어설 션을 단위 테스트해야합니까? ;)
mojuba

답변:


43

어설 션프로그램의 내부 상태 를 알려주는 데 유용합니다 . 예를 들어, 데이터 구조가 유효한 상태 (예 : Time데이터 구조가 값을 보유하지 않음)를 갖는 경우 25:61:61. 주장에 의해 확인 된 조건은 다음과 같습니다.

  • 발신자가 계약을 유지하도록하는 전제 조건

  • 수신자가 계약을 유지하도록 보장하는 사후 조건

  • 함수가 반환 된 후 데이터 구조가 항상 일부 속성을 보유하도록하는 불변량 불변은 전제 조건과 사후 조건 인 조건입니다.

단위 테스트모듈의 외부 동작에 대해 알려주는 데 유용 합니다 . 귀하는 Stack애프터 일관된 상태를 가질 수있다 push()메서드가 호출되지만이 세 번 호출 된 후 스택의 크기가 세 증가하지 않는 경우, 그 오류입니다. (예를 들어, 잘못된 push()구현이 어설 션 만 확인하고 종료 하는 사소한 경우 입니다.)

엄밀히 말하면 어설 션과 유닛 테스트의 주요 차이점은 유닛 테스트에는 테스트 데이터 (프로그램을 실행하는 데 필요한 값)가 있지만 어설 션은 그렇지 않다는 것입니다. 즉, 어설 션에 대해 동일하게 말할 수는 없지만 단위 테스트를 자동으로 실행할 수 있습니다. 이 논의를 위해, 당신은 고차 함수 테스트 (전체 프로그램을 실행하고 단위 테스트와 같은 모듈을 구동하지 않음)의 맥락에서 프로그램을 실행하는 것에 대해 이야기한다고 가정했습니다. "실제 입력을 보는"수단으로 자동화 된 기능 테스트에 대해 이야기하고 있지 않다면, 그 가치는 자동화에 있으며, 따라서 단위 테스트가 이길 것입니다. (자동) 기능 테스트의 맥락에서 이에 대해 이야기하고 있다면 아래를 참조하십시오.

테스트 대상에 약간의 중복이있을 수 있습니다. 예를 들어 Stack의 사후 조건은 실제로 스택 크기가 1 씩 증가한다고 주장 할 수 있습니다. 그러나 해당 주장에서 수행 할 수있는 작업에는 한계가 있습니다. 또한 최상위 요소가 방금 추가 된 항목인지 확인해야합니까?

둘 다 목표는 품질을 높이는 것입니다. 단위 테스트의 목표는 버그를 찾는 것입니다. 어설 션의 목표는 유효하지 않은 프로그램 상태가 발생하자마자 관찰하여 디버깅을보다 쉽게 ​​만드는 것입니다.

참고 기술은 정확성을 확인합니다. 실제로 프로그램이 올바른지 확인하기 위해 단위 테스트를 수행하면 제대로 작동 할 것이라는 흥미로운 테스트가 나올 것입니다. 그것은 심리적 효과입니다. 목표를 달성하기 위해 무엇이든 할 것입니다. 당신의 목표가 버그를 찾는 것이라면, 당신의 활동은 그것을 반영 할 것입니다.

둘 다 중요하며 자체 목적이 있습니다.

[어설 션에 대한 마지막 참고 사항 : 최대한의 가치를 얻으려면 몇 가지 주요 기능이 아니라 프로그램의 모든 중요 지점에서 사용해야합니다. 그렇지 않으면 문제의 원래 원인이 숨겨져 몇 시간 동안 디버깅하지 않고 감지하기 어려울 수 있습니다.]


7

어설 션에 대해 이야기 할 때는 스위치를 켤 때 끌 수 있습니다.

매우 잘못된 어설 션의 예 :

char *c = malloc(1024);
assert(c != NULL);

왜 이것이 나쁜가요? NDEBUG와 같은 정의로 인해 해당 어설 션을 건너 뛰면 오류 검사가 수행되지 않기 때문입니다.

단위 테스트는 위 코드에서 segfault 일 것입니다. 물론, 무언가 잘못되었다고 말함으로써 그 일을 했습니까? malloc()테스트에서 실패 할 가능성은 얼마나 됩니까?

어설 션은 프로그래머가 '정상적인'이벤트로 어설 션이 발생하지 않음을 암시해야 할 경우 디버깅 목적으로 사용됩니다. malloc()실패는 실제로 정상적인 사건이므로 절대로 주장해서는 안됩니다.

잘못 될 수있는 일을 적절히 처리하는 대신 어설 션을 사용하는 다른 많은 경우가 있습니다. 그렇기 때문에 어설 션의 평판이 나 빠지고 Go와 같은 언어에 포함되지 않은 이유가 있습니다.

단위 테스트는 변경 한 사항이 다른 항목을 위반 한 시점을 알려주기 위해 고안되었습니다. 빌드 할 때마다 프로그램의 모든 기능을 사용하지 않아도 (대부분의 경우) 테스터 릴리스에 중요합니다.

둘 사이에 어떤 일이 잘못되었다고 말해주는 것 외에는 둘 사이에 뚜렷한 상관 관계가 없습니다. 디버거를 사용하지 않고 어설 션을 작업중인 중단 점으로 생각하십시오. 단위 테스트는 당신 이하고 있지 않은 것을 깨뜨 렸는지 알려주는 것으로 생각하십시오 .


3
그렇기 때문에 어설 션은 항상 오류 테스트가 아니라 사실 진술이어야합니다.
Dominique McDonnell 5

@DominicMcDonnell 글쎄, '진실해야합니다'. 버그가있는 abs ()가 내장 된 특정 버전의 gcc와 같은 컴파일러 문제를 해결하기 위해 간혹 주장합니다. 기억해야 할 중요한 것은 프로덕션 빌드가 어쨌든 꺼져 야한다는 것 입니다 .
Tim Post

그리고 여기서는 생산 코드가 주장을 가장 필요로하는 곳이라고 생각합니다. 생산이 불가능하다고 생각하는 입력을 얻을 수 있기 때문입니다. 프로덕션은 가장 어려운 모든 버그를 일으키는 곳입니다.
Frank Shearar

@Frank Shearar, 매우 사실입니다. 프로덕션에서 가장 빨리 감지 된 오류 상태에서 여전히 실패해야합니다. 사용자가 불만을 제기 할 수는 있지만 버그가 수정 될 수있는 유일한 방법입니다. 그리고 나중에 몇 번의 함수 호출을 null로 나타내는 메모리 예외보다 blah가 0 인 것을 얻는 것이 훨씬 좋습니다.
도미니크 맥도넬

왜 발생하지 않아야한다고 주장하는 것보다는 일반적이지만 일반적이지 않은 (사용자의 관점에서) 문제를 처리하는 것이 더 좋은가? 나는이 지혜를 깨닫지 못한다. 물론 프라임 생성기는 프라임을 반환하므로 디버그 빌드에서 예상되는 약간의 추가 작업이 필요합니다. 언어가 기본적으로 테스트 할 수있는 것을 주장하는 것은 단지 어리석은 일입니다. 릴리스 후 몇 개월 동안 꺼질 수있는 다른 스위치로 테스트를 래핑하지 않고 훨씬 더 어리 석습니다.
Tim Post

5

두 도구 모두 구축중인 시스템의 전반적인 품질을 향상시키는 데 사용되는 도구입니다. 사용하는 언어, 작성하는 응용 프로그램 유형 및 시간이 가장 많이 소비되는 위치에 따라 다릅니다. 말할 것도없이 당신은 그것에 대해 몇 가지 생각의 학교를 가지고 있습니다.

먼저 assert키워드 없이 언어를 사용하는 경우 어설 션을 사용할 수 없습니다 (적어도 여기서 말하는 방식이 아님). 오랫동안 Java에는 assert키워드 가 없었으며 여전히 많은 언어가 없습니다. 그러면 단위 테스트가 더욱 중요해집니다. 일부 언어에서는 어설 션이 플래그가 설정된 경우에만 실행됩니다 (여기서는 Java와 함께). 보호 기능이 항상있는 것은 아니지만 유용한 기능은 아닙니다.

당신이 무언가를 "어설트 (asserting)"한다면 if/ throw의미있는 예외 블록을 쓸 수도 있다고 생각하는 학교가 있습니다 . 이 사고 과정은 모든 값이 한계 내에 있도록 방법의 시작 부분에 배치 된 많은 주장에서 비롯됩니다. 사전 조건 테스트는 예상되는 사후 조건을 갖는 데 매우 중요한 부분입니다.

단위 테스트는 작성하고 유지해야하는 추가 코드입니다. 많은 사람들에게 이것은 단점입니다. 그러나 현재 단위 테스트 프레임 워크를 사용하면 비교적 적은 코드로 많은 수의 테스트 조건을 생성 할 수 있습니다. 매개 변수화 된 테스트와 "이론"은 수많은 데이터 샘플로 동일한 테스트를 수행하여 찾기 어려운 버그를 발견 할 수 있습니다.

개인적으로 뿌리를 뿌리는 것보다 단위 테스트를 통해 더 많은 마일리지를 얻는다는 것을 알았습니다. 그러나 그것은 대부분의 시간에 개발 한 플랫폼 (Java / C #) 때문입니다. 다른 언어는보다 강력한 어설 션 지원을 제공하며 "계약에 의한 설계"(아래 참조)를 통해 더 많은 보증을 제공합니다. 이러한 언어 중 하나를 사용하는 경우 단위 테스트보다 DBC를 더 많이 사용할 수 있습니다.

http://en.wikipedia.org/wiki/Design_by_contract#Languages_with_native_support

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