2013-03-11 8 views
1

현재 CppUnit을 사용하여 C++로 단위 테스트를 작성하고 있습니다. 시험의 컴파일하는 동안 경고가 VS2010에서 (나를 놀라게CppUnit은 Assert로 예외를 예상합니다. C4127로 컴파일합니다.

CPPUNIT_ASSERT_THROW(
    boost::get<FooClassInBoostVariant>(m_boostVariantFooOrBar), 
    boost::bad_get); 

하지만,뿐만 아니라 다른 컴파일러에 경고가 될 것입니다 : 최근에 나는 예외가 CppUnits 매크로를 사용하여 특정 경우에 발생되어 있는지 확인해야했습니다. ..) :

warning C4127: conditional expression is constant 

나는 CppUnit을의 매크로 정의로보고 다음과 같은 발견이 어떻게 작동하는지

do {               \ 
    bool cpputExceptionThrown_ = false;       \ 
    try {               \ 
    expression;            \ 
    } catch (const ExceptionType &) {       \ 
    cpputExceptionThrown_ = true;        \ 
    }                \ 
                   \ 
    if (cpputExceptionThrown_)         \ 
    break;              \ 
                   \ 
    CPPUNIT_NS::Asserter::fail(         \ 
       "Expected exception: " #ExceptionType   \ 
       " not thrown.",        \ 
       CPPUNIT_SOURCELINE());      \ 
} while (false) 

글쎄, 내가 완전히 이해 루프 동안 할 일을 내가 s가 false로 인해 한 번만 실행되고 break는 Asserter :: fail() 부분을 실행하지 않는 데 사용됩니다. 그런데 왜 그들이 이렇게하고 있니? 물론 while 루프의 중단 조건은 항상 "거짓"이므로 컴파일러 경고를 트리거합니다. 그러나 이것을하기위한보다 우아한 방법은 없을까요? 나는 보통 경고없는 컴파일 원리를 고수한다. 그래서 이것은 정말로 나를 괴롭힌다.

그래서 제 질문은 정말이며, 그들은 왜 이런 식으로 구현하지 않았다

{                \ 
    bool cpputExceptionThrown_ = false;       \ 
    try {               \ 
    expression;             \ 
    } catch (const ExceptionType &) {       \ 
    cpputExceptionThrown_ = true;        \ 
    }                \ 
                   \ 
    if (!cpputExceptionThrown_) {        \ 
    CPPUNIT_NS::Asserter::fail(        \ 
       "Expected exception: " #ExceptionType   \ 
       " not thrown.",        \ 
       CPPUNIT_SOURCELINE());      \ 
    }                \ 
} 

사전에 감사!

-Hannes

+2

대부분 무능력이지만 코딩 스타일 일 수도 있습니다. btw 그것은 cppunit의 유일한 문제가 아닙니다. 캐스팅하지 않고 부호없는 short 정수를 비교해보십시오. –

+0

수십개의 다른 제약이 수년 전에 대규모 프로젝트에서 CppUnit을 사용하기로 결정했을 수도 있기 때문에 유용한 힌트가 아닌 더 나은 단위 테스트 프레임 워크 (gtest와 같은) –

+2

으로 변경하는 것이 좋습니다. 이 프레임 워크 내에서 ...하지만 처음부터 나는 더 이상 CppUnit을 선택하지 않을 것이라고 생각합니다. –

답변

1

OK, 나는 나 자신에 의해 답을 발견 같아요

http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/는 설명을 제공합니다.

do { } while (false);에 여러 줄 매크로를 래핑하는 것이 일반적입니다. 이것은 예를 들어 브레이스되지 않은 if else과 같이 해당 매크로를 사용할 수있는 해결 방법입니다.

if (condition_a) 
    MULTI_LINE_MACRO(); 
else 
    MULTI_LINE_MACRO_2(); 

예기치 않게 첫 번째 행만 실행되면 예기치 않은 동작이 발생합니다. 그래서 그들은 완전히 무능한 것은 아니 었습니다 ...

http://kernelnewbies.org/FAQ/DoWhile0 또한 내 솔루션이 작동하지 않는 이유를 설명합니다. if 내에있는 MULTI_LINE_MACRO();은 (condition_a) {/ * 매크로 stuff * /} 인 경우 으로 확장합니다. ; else // < < 때문에 실행되지 않았습니다. 위.

그래서 경고를 비활성화해야합니다. GCC는 Statement Expression라고하는이 workwork (({ MACRO }))를 가지고 있지만, VS2010에서 작동하지 않는다고 생각합니다.

+0

내 대답을 아래의 편집 내역 참조 - C++ 11 지원이있는 경우 lambdas를 사용할 수 있습니다 –

2

이유는 주장을 한 문장을 만드는 것입니다. 매크로의 두 가지 용도를 고려 코드가 do { ... } while (false) doSomething();로 확장 이후 자신의 코드와

CPPUNIT_ASSERT_THROW(foo(), MyException); // a 
CPPUNIT_ASSERT_THROW(foo(), MyException) // b - without trailing `;`! 
doSomething(); 

, 당신은 //b에 오류가 발생하는 것입니다 - 당신이 조건 후 ;를 누락 될 것입니다. 코드와

, //b 행복하게 컴파일,하지만 그 선 블록 후 superfluos으로, { ... };;을 확장 것이기 때문에 //a, 당신에게 "하늘의 문"경고를 줄 수 있습니다. 하지만 각 줄 후 ;을 그냥 일관성이기 때문에 더 //b 방법을 좋아한다 -

당신은 내가 모르는 //a를 사용하는 이유는

. 어설 션과 라인을 구분할 필요가 없습니다.

PS : 나는 확실하지 않다하지만 { ... } 블록 간단한 블록이 허용되지 않는 곳 곳에서 주장 매크로를 넣을 수 do {...} while(false) 문 사이에 많은 차이가있을 수 있습니다.

편집 : C++ (11)와 함께, 당신은 람다를 사용할 수 (정의하고 한 곳에서 호출) : 그러나

#define CPPUNIT_ASSERT_THROW(expression, ExceptionType)   \ 
[&]() -> void {             \ 
    bool cpputExceptionThrown_ = false;       \ 
    try {               \ 
    expression;            \ 
    } catch (const ExceptionType &) {       \ 
    cpputExceptionThrown_ = true;        \ 
    }                \ 
                   \ 
    if (cpputExceptionThrown_)         \ 
    return;             \ 
                   \ 
    CPPUNIT_NS::Asserter::fail(         \ 
       "Expected exception: " #ExceptionType   \ 
       " not thrown.",        \ 
       CPPUNIT_SOURCELINE());      \ 
}() 

,주의 사항이있을 수 있습니다, 예를 들어, 표현식에서 사용하는 변수를 캡처하는 람다 때문에.

+0

람다는 멋진 아이디어지만 불행히도이 프로젝트에서 C++ 11을 사용할 수 없습니다. -/ –