2012-03-12 3 views
21

헤더 전용 C++ 라이브러리 (많은 템플릿 등)에 대해 GCov를 사용하여 테스트 적용 범위를 확인합니다. 그러나 사용되지 않는 함수가 컴파일러에 의해 처음 생성되지 않기 때문에 모든 헤더에 대해 100 % 적용 범위를보고합니다. 발견 된 기능을 수동으로 발견하는 것은 쉽지만 지속적인 통합의 목적을 무효로합니다 ...헤더 전용 라이브러리에 대한 유용한 GCov 결과 얻기

어떻게 자동으로이 문제를 해결합니까? 나는 단지 "라인 히트/LOC"를 나의 커버리지 메트릭으로 사용하고 결코 100 % 다시 도달하지 않아야합니까?

+1

당신은 모든 공용 메서드와 함수를 호출하는 단위 테스트를 할 수 있습니다 (그래서 lcov에 대한) 당신 * .gcno 파일을 초기화 있는지 확인하십시오. 동시에 적용되는지 테스트 할뿐만 아니라 적용 범위를 얻을 수 있습니다. –

+2

그래,하지만 기능을 놓친다면 쉽게 발견하고 싶다. 단지 내 CDash를 탐색하고 <100 % 적용 범위의 헤더를 볼 수 있다면 좋을 것이다. – pascal

+0

나는 또한이 질문에 대한 좋은 대답을했습니다. 1. 나는 그럴듯한 인스턴스화를 보는 것이 좋을 것이라는데 동의한다. 2.(템플릿 클래스에서) 멤버 템플릿에 대한 결과를 보지 못했습니다. 여기서는 인스턴스 코드가 내 테스트 코드 (조금 이상합니다) 내에서 호출된다는 것을 절대적으로 확신합니다. –

답변

12

GCC 제어 인라 이닝에 대한 일반적인 플래그는 따로하고;

--coverage -fno-inline -fno-inline-small-functions -fno-default-inline 

단위 테스트 파일의 맨 위에 템플릿 클래스를 인스턴스화 할 수 있습니다.

template class std::map<std::string, std::string>; 

이렇게하면 해당 템플릿 클래스의 모든 메소드에 대한 코드가 생성되어 적용 도구가 완벽하게 작동합니다.

또한,

lcov -c -i -b ${ROOT} -d . -o Coverage.baseline 
<run your tests here> 
lcov -c -d . -b ${ROOT} -o Coverage.out 
lcov -a Coverage.baseline -a Coverage.out -o Coverage.combined 
genhtml Coverage.combined -o HTML 
1

또한 테스트 커버리지 (Google Test 프레임 워크로 작성된 테스트)를 확인하기 위해 GCov를 사용하고 있으며, Eclipse GCov 통합 플러그인 또는 LCov 도구를 사용하여 테스트 커버리지 결과를 쉽게 검토 할 수 있습니다. 원시 GCov 출력은 너무 사용하기가 어렵습니다. (

헤더 전용 템플릿 라이브러리가있는 경우 템플릿 클래스 및 템플릿 멤버 함수를 인스턴스화하는 테스트 클래스를 측량 (G ++ 플래그 - 커버리지 사용)해야합니다. 이러한 합리적인 gcov의 출력을 볼 수 있습니다.이 모든 테스트 케이스 인스턴스화되지 않은 템플릿 코드를 발견하는 것은 쉽다 언급 된 도구와

를, 그것은 어떠한 주석이 없습니다 때문이다.

을 내가 설정에게 샘플을 가지고 LCov 출력을 검사 할 수있는 DropBox 링크에 복사했습니다.

샘플 코드 (T

#include <string> 
#include "gtest/gtest.h" 
#include "TemplateSample.hpp" 

class TemplateSampleTest : public ::testing::Test 
{ 
public: 

    TemplateSampleTest() 
    : templateSample(5) 
    { 
    } 

protected: 
    TemplateSample<int> templateSample; 

private: 
}; 

TEST_F(TemplateSampleTest,doSomethingPath1) 
{ 
    EXPECT_EQ(1,templateSample.doSomething(TemplateSample<int>::Path1)); 
} 

TEST_F(TemplateSampleTest,doSomethingPath2) 
{ 
    EXPECT_EQ(2,templateSample.doSomething(TemplateSample<int>::Path2)); 
} 

TEST_F(TemplateSampleTest,returnRefParam) 
{ 
    std::string stringValue = "Hello"; 
    EXPECT_EQ(stringValue,templateSample.returnRefParam(stringValue)); 
} 

TEST_F(TemplateSampleTest,doSomethingElse) 
{ 
    std::string stringValue = "Hello"; 
    long value = templateSample.doSomethingElse<std::string,long>(stringValue); 
    EXPECT_EQ(5,value); 
} 

여기 lcov에서 생성 된 코드 커버리지 출력을 참조하십시오 TemplateSampleTest.cpp

TemplateSample.hpp

template<typename T> 
class TemplateSample 
{ 

public: 
    enum CodePath 
    { 
     Path1 , 
     Path2 , 
     Path3 , 
    }; 

    TemplateSample(const T& value) 
    : data(value) 
    { 
    } 

    int doSomething(CodePath path) 
    { 
     switch(path) 
     { 
     case Path1: 
      return 1; 
     case Path2: 
      return 2; 
     case Path3: 
      return 3; 
     default: 
      return 0; 
     } 

     return -1; 
    } 

    template<typename U> 
    U& returnRefParam(U& refParam) 
    { 
     instantiatedCode(); 
     return refParam; 
    } 

    template<typename U, typename R> 
    R doSomethingElse(const U& param) 
    { 
     return static_cast<R>(data); 
    } 

private: 
    void instantiatedCode() 
    { 
     int x = 5; 
     x = x * 10; 
    } 

    void neverInstantiatedCode() 
    { 
     int x = 5; 
     x = x * 10; 
    } 
    T data; 
}; 

: emplateSampleTest.cpp는 g ++ --coverage 옵션)를 사용하여 계측한다 :

TemplateSample.hpp coverage

경고 : '기능'통계는 100 %로보고됩니다. 이는 실제로 인스턴스화되지 않은 템플릿 기능에 대해서는 사실이 아닙니다.