2008-11-06 3 views
15

부스트 테스트 프레임 워크를 사용하여 C++ 코드를 단위 테스트하고 함수가 어설 션되는지 테스트 할 수 있는지 궁금한가요? 예, 약간 이상하게 들리지만 나와 함께 감내주십시오! 많은 함수가 입력시 입력 매개 변수를 검사하고 유효하지 않은지 여부를 확인하므로이 값을 테스트하는 것이 유용합니다. 예를 들어 :부스트 테스트 프레임 워크에서 어설 션 테스트

void MyFunction(int param) 
{ 
    assert(param > 0); // param cannot be less than 1 
    ... 
} 

나는 이런 식으로 뭔가를 할 수 있도록하고 싶습니다 :

BOOST_CHECK_ASSERT(MyFunction(0), true); 
BOOST_CHECK_ASSERT(MyFunction(-1), true); 
BOOST_CHECK_ASSERT(MyFunction(1), false); 
... 

당신은 좀 너무 마법 주장이 있다면 궁금 있도록 부스트 테스트를 사용하여 발생되는 예외를 확인할 수 있습니다. ..

+0

나는 이것이 오래된 주제라는 것을 알고 있지만, 직장에서 자신을 도왔던 해결책을 추가했습니다. – grokus

답변

5

나는 그렇게 생각하지 않는다. 예외를 던지는 자신 만의 어설 션을 작성한 다음 해당 예외에 대해 BOOST_CHECK_NOTHROW()를 사용할 수 있습니다.

0

죄송합니다. 그러나 문제는 잘못된 방법으로 공격하고 있습니다.

"assert"는 악마 (a.k.a. "C")의 생성이며 적절한 예외가있는 언어에서는 쓸모가 없습니다. 예외가있는 assert-like 기능을 다시 구현하는 것이 좋습니다. 이렇게하면 올바른 방법으로 오류를 처리하거나 (적절한 정리 절차 포함) 또는 원하는대로 오류를 발생시킬 수 있습니다 (단위 테스트 용).

게다가 코드가 Windows에서 실행되는 경우 어설 션에 실패하면 디버그/중단/다시 시도를 제공하는 쓸모없는 팝업이 표시됩니다. 자동 단위 테스트에 좋습니다.

그래서 예외를 throw하는 assert 함수를 다시 작성하고 코드를 다시 작성하십시오. 하나는 여기있다 : 당신이 얻을 수 있도록 How can I assert() without using abort()?

이 _ _file _ _ 및 _ _ 라인은 _ _ (디버그에 유용)와이 완료 매크로에 랩.

+12

당신이 이것을 사용하고 있다고 믿는다면 잘못된 방법을 주장합니다. 어설 션은 사실이어야하거나 * 프로그래머 * 오류 인 경우에만 사용해야하며 질문에 제공된 예를 참조하십시오. 프로그래머가 잘못된 방식으로 함수를 사용하면 가능한 한 빨리 그 함수를 알고 싶습니다. –

+1

나는 Andreas에 동의한다. 어설 션 및 가능한 경우 static_asserts를 예외로 대체하면 안됩니다. 그들은 프로그래머의 오류를 감지하기위한 것입니다. –

+4

그리고 프로그래머의 실수로 어떻게합니까? 크래시 및 하드 열심히 ??? 진지해, 사람들. 주장은 시대에 뒤떨어져 있습니다. 현대 코드에서 사용하는 것에 대한 변명의 여지가 없습니다. 그리고 당신은 "가능한 빨리 알기를 원합니다."그러고 나서 "붙잡기 (...)"를 그만하십시오. – rlerallut

9

확인하고 싶은 오류에는 invariants와 런타임 오류 두 가지가 있습니다.

불변 식은 무엇이든지간에 항상 참이어야합니다. 그것들을 위해서 나는 주장을 사용한다. 너 같은 게 나에게주는 출력 버퍼에 제로 포인터를 넘겨서는 안된다. 이것은 코드의 버그입니다. 간단하고 간단합니다. 디버그 빌드에서, 그것은 주장하고 나에게 그것을 수정할 수있는 기회를 제공합니다. 리테일 빌드에서는 액세스 위반이 발생하고 최소 덤프 (Windows, 적어도 코드) 또는 코어 덤프 (Mac/Unix)를 생성합니다. 내가 할 수있는 catch은 0 포인터를 역 참조하는 것을 다루는 것이 타당합니다. Windows에서 catch (...)은 액세스 위반을 억제하고 사용자가 이미 끔찍하게 끔찍하게 잘못했을 때 문제가 없다는 잘못된 인식을 사용자에게 줄 수 있습니다.

이 내가 catch (...)는 C의 코드 냄새 ++ 내가 그 것을 현재 생각할 수있는 유일한 합리적인 장소는 일반적으로 main (또는 WinMain)를 사용하면 코어를 생성하기 직전에 있음을 믿게 한 이유 중 하나입니다 덤프하고 정중하게 앱을 종료합니다.

런타임 오류는 "사용 권한으로 인해이 파일을 쓸 수 없습니다."또는 "디스크가 꽉 찼기 때문에이 파일을 쓸 수 없습니다."와 같은 오류가 있습니다. 사용자가 디렉토리에 대한 권한을 변경하거나, 일부 파일을 삭제하거나, 다른 위치를 선택하여 파일을 저장하는 등의 작업을 수행 할 수 있기 때문에 이러한 종류의 오류에 대해서는 예외가 발생합니다. 이러한 런타임 오류는 사용자가 수정할 수 있습니다. 불변 식의 위반은 사용자가 수정할 수 없으며 프로그래머 만 수정할 수 있습니다. 때로는 두 가지가 같지만 일반적으로 두 가지가 동일하지 않습니다.)

단위 테스트는 코드가 생성 할 수있는 런타임 오류 예외를 throw하도록합니다. 또한 테스트중인 시스템이 예외 안전하다는 것을 확인하기 위해 협력자의 예외 사항을 강제 실행할 수 있습니다.

그러나 나는 단위 테스트를 사용하여 코드가 invariant에 대해 어설 션되도록하는 데 가치가 있다고 생각하지 않습니다.

3

나는이 질문과 응답 중 일부는 런타임 오류 탐지와 버그 감지를 혼동한다고 생각한다. 그들은 또한 의도와 메커니즘을 혼동합니다.

런타임 오류는 100 % 올바른 프로그램에서 발생할 수 있습니다. 탐지가 필요하며 적절한보고 및 처리가 필요하며이를 테스트해야합니다. 버그도 발생하며 프로그래머의 편의를 위해 사전 조건 검사 또는 불변 검사 또는 무작위 주장을 사용하여 조기에 파악하는 것이 좋습니다. 그러나 이것은 프로그래머의 도구입니다. 이 오류 메시지는 일반 사용자에게는 아무런 의미가 없으며 제대로 작성된 프로그램이 절대로 통과하지 못하는 데이터에 대해 함수 동작을 테스트하는 것이 타당하지 않은 것으로 보입니다.

의도와 메커니즘에 관해서는 예외는 아무 것도 없다는 점에 유의해야합니다. 얼마 전 Peter Drimov는 Boost 메일 링리스트 (약)에서 "예외는 단지 비 로컬 점프 메커니즘"이라고 말했습니다. 그리고 이것은 매우 사실입니다. 일부 내부 오류가 발생한 후에도 계속 응용 프로그램을 사용할 수있는 경우 복구 전에 무언가가 손상 될 위험없이 C++ 예외를 throw하는 사용자 지정 어설 ​​션을 구현할 수 있습니다. 그러나 그것은 의도를 바꾸지 않을 것이며 훨씬 더 합리적인 주장을 테스트하지 않을 것입니다.

12

같은 문제가있어서 문서 (코드)를 파고 에서 "해결책"을 발견했습니다.

부스트 UTF는 boost::execution_monitor ( <boost/test/execution_monitor.hpp>)을 사용합니다. 이것은 테스트 실행 중에 발생할 수있는 모든 것을 잡으려고 목적으로 고안되었습니다. 어설 션이 발견되면 execution_monitor가 인터셉트하여 boost::execution_exception을 발생시킵니다. 따라서 BOOST_REQUIRE_THROW을 사용하면 어설 션 오류가 발생할 수 있습니다.

그렇게 :

#include <boost/test/unit_test.hpp> 
#include <boost/test/execution_monitor.hpp> // for execution_exception 

BOOST_AUTO_TEST_CASE(case_1) 
{ 
    BOOST_REQUIRE_THROW(function_w_failing_assert(), 
         boost::execution_exception); 
} 

트릭을 할해야합니다. (. 그것은 나를 위해 작동)

그러나

(또는 부인) :

  • 그것은 나를 위해 작동합니다. 즉, Windows XP에서 MSVC 7.1은 1.41.0을 향상시킵니다. 이 설치에 적합하지 않거나 손상 될 수 있습니다.

  • 부스트 테스트의 저자의 의도는 아닙니다. (비록 이것이 execution_monitor의 목적 인 것 같지만).

  • 같은 방식으로 모든 유형의 치명적인 오류를 처리합니다. 나는 당신의 단언 이외의 무엇인가가 실패하고 있다고 일 수있다. 이 경우 은 메모리 손상 버그를 놓치거나 실패한 실패한 어설 션을 놓칠 수 있습니다.

  • 향후 부스트 버전에서 중단 될 수 있습니다.

  • 어설 션은 이 비활성화되고 어설 션이 금지 된 코드는 이 실행되므로 릴리스 구성에서 실행하면 오류가 발생할 것으로 예상됩니다. 매우 정의되지 않은 동작이 발생합니다.

  • msvc의 릴리스 구성에서 일부 어설 션 또는 기타 치명적인 오류 이 발생하더라도 어쨌든 발생하지 않습니다. (execution_monitor 문서 참조).

  • 어설 션을 사용하거나 사용하지 않는 것은 귀하에게 달려 있습니다. 나는 그들을 좋아해.

참조 :

, 나디 Rozental (부스트 시험의 저자) 덕분에, 당신은 에 일어나는 경우에이 글을 읽을 위대한 작품!

+0

나를 위해 작동하지 않았다 - debian gcc 4.4.6 – sje397

+0

우분투 14.04, 부스트 1.55, gcc 4.8.2 – RichardBruce

+0

나를 위해 작동하지 않았다 gcc 4.8.1 centOs 2.6.x – bjackfly

2

나는 똑같은 문제를 겪었다. 내 솔루션은 컴파일 플래그를 사용하는 것입니다. GROKUS_TESTABLE 플래그가 켜지면 GROKUS_ASSERT가 예외로 바뀌고 Boost를 사용하면 예외를 throw하는 코드 경로를 테스트 할 수 있습니다. GROKUS_TESTABLE이 꺼져 있으면 GROKUS_ASSERT가 C++ assert()로 변환됩니다.

#if GROKUS_TESTABLE 
#define GROKUS_ASSERT ... // exception 
#define GROKUS_CHECK_THROW BOOST_CHECK_THROW 
#else 
#define GROKUS_ASSERT ... // assert 
#define GROKUS_CHECK_THROW(statement, exception) {} // no-op 
#endif 

내 원래의 동기가 디버깅, 즉 어설 도움이었다() 신속하게 디버깅 및 예외는 종종 GDB로 디버깅하기 어렵다 할 수있다. 내 컴파일 플래그 디버깅 가능성과 테스트 가능성을 꽤 잘 균형을 것 같다.

호프이 도움이 되었습니까?