2010-08-24 15 views
36

gcov를 사용하여 C++ 코드의 범위를 측정합니다. 나는 100 % 적용 범위에 도달하고 싶지만, 이론적으로 타격을 입을 수없는 몇 줄의 코드 (구현해야하지만 실제로는 호출되지 않는 메서드 인 switch 문) 기타.). 각 분기에는 assert(false); 문이 포함되어 있지만 gcov는 여전히 해당 문구를 un hit로 표시합니다.gcov가 C++ 코드의 히트 라인을 무시하도록 어떻게 선언합니까?

나는이 브랜치들을 무시하도록 gcov에게 말하고 싶다. gcov에게 그 정보를 제공 할 수있는 방법이 있습니까? - 소스 코드에 주석을 달거나 다른 메커니즘을 사용합니까?

+0

는 선이 unhittable 것을 당신이 그렇게 확실하게 무엇? 당신이 그들을 때릴 수 없기 때문에 그것이라면, 당신이 코드 커버리지로 찾으려고하는 것입니다. – doron

+2

@ deus-ex-machina399 : 아니요. 내가 그들을 때리지 못했기 때문이 아닙니다. 그것은 코드의 이해와 분석 때문입니다. 물론, 나는 틀릴 수도 있지만 코드 커버리지 분석을 사용하여 소스 코드에 대한 내 이해를 검증하려고하지는 않습니다. 필자는 테스트 커버리지의 품질을 검증하기 위해 코드 커버리지 분석을 사용하고 있습니다. – jchl

+1

@doron, unhittable해야하는 코드의 한 예는 테스트 인프라의 실패 경로입니다. 물론, 당신은 아마 그런 경로없이 할 수 있지만, 나는 그것들을 가지고있다. –

답변

35

lcov를 사용하십시오.다음

: geninfo에서

(1) : 이미 검토 라인 라인 마커 - 그것은, gcov가의 복잡성을 숨 깁니다 좋은 출력을 생성, 테스트 당 자세한 출력을 할 수 있습니다, 쉬운 파일 필터링 기능 - TA-TAA를

  • LCOV_EXCL_LINE이 마커를 포함
    • 라인은 제외됩니다 마커는 geninfo에 의해 인식됩니다.
    • LCOV_EXCL_START는 제외 된 부분의 시작을 표시. 현재 줄은이 섹션의 일부입니다.
    • LCOV_EXCL_STOP는 제외 된 부분의 끝을 표시. 현재 행은이 섹션의 일부가 아닙니다.
+0

흥미 롭다. 나는 lcov에 대해 들어 보지 못했다. 추천 주셔서 감사합니다! – jchl

+0

마침내 이것을 테스트 해 보았습니다 ... 그리고 lcov> = 1.8 버전으로 업그레이드 한 후에 그것은 매력을 발휘합니다. 감사! – jchl

+14

나는 "다른 도구 사용하기"형식의 답을 좋아하지 않습니다. 실제로 gcov에서 줄을 무시하는 방법을 알고 싶습니다. lcov로 전환 할 수있는 옵션이 없습니다. 그래서 이것은 질문에 대답하지 않습니다. –

0

나는 이것이 가능하다고 생각하지 않습니다. Gcov는 gcc에 의존하여 추가 코드를 생성하여 범위 출력을 생성합니다. GCov 자체는 데이터를 파싱합니다. 이것은 Gcov가 gcc보다 코드를 더 잘 분석 할 수 없다는 것을 의미합니다 (그리고 여러분은 -Wall을 사용하고 도달 할 수없는 것으로보고 된 코드를 제거했다고 가정합니다).

재배치 가능한 함수는 외부 dll이나 실행 파일에서도 잠재적으로 호출 될 수 있으므로 컴파일러에서 호출 할 수없는 재배치 가능 함수 또는 이러한 함수가 가질 수있는 입력을 컴파일러에서 알 수있는 방법이 없음을 기억하십시오.

아마도 원하는 정적 인 분석 도구를 사용해야합니다.

1

이론적으로 불가능한 코드 경로를 직접 공격하여 gcov를 종료 할 수있는 관련 기능의 단위 테스트를 도입 할 수 있습니까? 단위 테스트이기 때문에 상황의 "불가능"을 무시할 수 있습니다. 그들은 결코 호출되지 않는 함수를 호출하거나 기본 분기를 포착하기 위해 유효하지 않은 열거 형 값을 전달할 수 있습니다.

그런 다음 NDEBUG로 컴파일 된 코드 버전에서만 테스트를 실행하거나 테스트하는 하네스에서 실행하십시오 테스트 프레임 워크가 지원하는 것이 무엇이든간에 어설 션이 트리거됩니다.

코드에 대한 기능 요구 사항을 포함하는 스펙보다는 코드가 있어야한다고 스펙에서 다소 이상하다고 생각합니다. 특히 테스트가 이러한 요구 사항을 테스트하지 않고 있다는 것을 의미합니다. 이는 요구 사항을 기능적으로 유지하는 데 좋은 이유입니다. 개인적으로 "잘못된 enum 값으로 호출 된 경우 함수는 assert을 실패하고 발신자는 릴리스 모드에서 유효하지 않은 enum 값을 가진 함수를 호출하지 않아야합니다"라는 사양을 수정하고 싶습니다. " 또는 일부 그러한.

아마도 현재 말하는 모든 스위치 문은 기본 사례가 있어야합니다. 그러나 이것은 코딩 표준이 데드 코드를 도입함으로써 관찰 가능한 동작 (적어도 gcov에서 관찰 가능)을 방해한다는 것을 의미합니다. 코딩 표준이 그렇게해서는 안되기 때문에 가능한 경우 코딩 표준을 기능적 사양에서 고려해야합니다.

실패하면 unhittable 코드를 #if !GCOV_BUILD에 넣고 gcov의 이점을 위해 별도의 빌드를 수행 할 수 있습니다. 이 빌드는 몇 가지 요구 사항을 충족시키지 못하지만 올바른 코드 분석을 조건으로하면 테스트 스위트가 다른 모든 것을 테스트한다는 확신을 얻을 수 있습니다.

편집 : 당신은 dodgy 코드 생성기를 사용하고 있지만 소스 코드에 주석을 달아 솔루션을 요청할 수도 있습니다. 소스를 변경하는 경우 대부분의 경우 데드 코드를 제거 할 수 있습니까? 생성 된 소스를 변경하는 것이 이상적은 아니지만 필요합니다 ...

+0

"spec"이 함수가 있어야한다고 말하는 것은 아닙니다. 함수의 프로토 타입을 생성하는 코드 생성기가 있지만 사용되지는 않습니다. (코드 생성기를 수정하는 것이 더 좋을지 모르겠지만 불행히도 내 통제하에 있지는 않습니다.)이 때가끔 생기는 또 다른 상황은 인터페이스를 구현하는 것입니다 (즉, 순수 가상 함수를 사용하여 클래스에서 파생). 해당 인터페이스의 일부. – jchl

+0

NDEBUG 빌드에서 테스트를 실행하는 것은 힘들 수 있지만 (현재 단위 테스트는 모두 디버그 빌드에서 실행 됨) 단위 테스트 호출을 직접 수행하는 것은 나쁜 생각이 아닙니다. 그것은 가치가있는 것보다 더 많은 일처럼 들립니다. 나는 문서화 목적으로 거기에있는 것을 좋아하지만, 그 주장을 없앨 수 있습니다. 나는 단위 테스트를하는 동안을 제외하고 결코 잡히지 않는 특별한 예외를 던지면서 그것들을 대체 할 수있다. 그것은 나쁜 생각이 아니다. – jchl

+0

@jchl : "인터페이스를 구현 중입니다. 즉, 순수 가상 함수가있는 클래스에서 파생되었지만 해당 인터페이스의 일부만 사용하고 있습니다." - 일종의. 클래스에 대한 포괄적 인 테스트를 작성했다면 클래스를 정의하고 테스트에서 사용하지 않는 함수를 호출하여 테스트를 수행하도록 할 수 있습니다. 포괄적 인 테스트를 작성하지 않은 경우 코드 커버리지 여부에 상관하지 않습니다. –