단위 테스트 효율성을 극대화하려면 C ++ 단위 테스트 코드를 어떻게 구성해야합니까?


47
  • 이 질문은 단위 테스트 프레임 워크에 관한 것이 아닙니다 .
  • 이 질문은 단위 테스트 작성에 관한 것이 아닙니다 .
  • 이 질문은 UT 코드를 어디에 작성하고 언제 어떻게 컴파일하고 실행할지에 관한 것입니다.

에서 레거시 코드와 효과적으로 협력 , 마이클 깃털 주장

좋은 단위 테스트 ... 빠른 실행

그리고

실행하는 데 1/10 초가 걸리는 단위 테스트는 느린 단위 테스트입니다.

나는 이러한 정의가 의미가 있다고 생각합니다. 또한 그들은 단위 테스트 세트와 별도로 오래 걸리는 코드 테스트 세트를 유지해야 함을 암시한다고 생각 하지만 (매우) 빠르게 실행될 때 단위 테스트를 호출하는 데 드는 비용입니다. .

분명히 문제 ++ C의는 "실행"에 당신의 단위 테스트 ( ), 당신이 있습니다

  1. 코드를 편집하십시오 (귀하의 "사이클"에 따라 생산 또는 단위 테스트)
  2. 엮다
  3. 링크
  4. 시작 단위 테스트 실행 ( )

편집 (이상한 투표 후) : 세부 사항으로 들어가기 전에 요점을 요약 해 보겠습니다.

C ++ 단위 테스트 코드를 효과적으로 구성하여 (테스트) 코드를 편집하고 테스트 코드를 실행하는 것이 효율적일 수 있습니까?


번째 문제 는 유닛 테스트 코드를 어디에 둘 것인지 결정 하는 것입니다.

  • 관련 프로덕션 코드와 함께 편집하고 보는 것이 "자연 스럽다".
  • 현재 변경중인 유닛 의 컴파일 사이클을 시작하는 것이 쉽고 빠릅니다.

둘째 , 관련 문제는이고 어떤 피드백이 순간이되도록 컴파일.

극단적 인 옵션 :

  • 각 Unit-Test-Test-Unit은 별도의 cpp 파일에 존재하며이 cpp 파일은 테스트하는 소스 코드 단위 파일과 함께 개별적으로 컴파일 및 링크되어 단일 실행 파일로 컴파일 된 다음이 단일 단위 테스트를 실행합니다.
    • [+) 단일 테스트 장치의 시작 (컴파일 + 링크!) 시간을 최소화합니다.
    • (+) 한 단위 만 테스트하기 때문에 테스트가 매우 빠르게 실행됩니다.
    • (-) 전체 제품군을 실행하려면 일련의 프로세스를 시작해야합니다. 관리 문제가 될 수 있습니다.
    • (-) 프로세스 시작 오버 헤드가 표시됩니다
  • 다른 쪽은 테스트 당 하나의 cpp 파일을 가지고 있지만 모든 테스트 cpp 파일은 (테스트하는 코드와 함께!) 하나의 실행 파일에 연결됩니다 (모듈 당 / 프로젝트 / 선택).
    • (+) 변경된 코드 만 컴파일되므로 컴파일 시간은 여전히 ​​괜찮습니다.
    • (+) 하나의 exe 만 실행하면 전체 제품군을 쉽게 실행할 수 있습니다.
    • (-) 모든 객체를 재 컴파일 할 때마다 재 링크가 트리거되므로 스위트에 연결하는 데 시간이 걸립니다.
    • (-) (?) 모든 유닛 테스트가 빠르 더라도 시간이 충분해야 슈트를 실행하는 데 시간이 오래 걸립니다 .

실제 C ++ 단위 테스트 는 어떻게 처리됩니까? 매일 밤 / 시간마다 그 물건을 운영한다면, 두 번째 부분은 실제로 중요하지 않지만 첫 번째 부분, 즉 UT 코드를 프로덕션 코드에 "커플 링"하는 방법은 개발자가 두 가지를 모두 유지하는 것이 "자연적"입니다. 초점은 항상 내가 생각하는 문제입니다. (그리고 개발자가 UT 코드에 중점을 둔다면, 그것을 실행하고 싶을 것입니다.

실제 이야기와 경험에 감사드립니다!

노트:

  • 이 질문은 의도적으로 지정되지 않은 플랫폼 및 제작 / 프로젝트 시스템을 남깁니다.
  • 태그가 지정된 UT & C ++ 는 시작하기에 좋은 곳이지만 불행히도 너무 많은 질문, 특히 답변은 세부 사항이나 특정 프레임 워크에 너무 집중되어 있습니다.
  • 얼마 전, 부스트 단위 테스트 구조에 대해 비슷한 질문 에 대답했습니다 . 이 구조에는 "실제"의 빠른 단위 테스트가 부족하다는 것을 알았습니다. 그리고 다른 질문은 너무 좁아서 새로운 질문입니다.

6
시간을 컴파일하기 위해 가능한 많은 오류를 이동시키는 C ++ 관용구에 의해 더 복잡한 문제가 발생합니다. 좋은 단위 테스트 스위트는 종종 특정 사용법이 컴파일되지 않음을 테스트 할 수 있어야합니다.

3
@Closers :이 질문을 끝내게 한 논쟁을 제공해 주시겠습니까?
Luc Touraille

왜 이것이 닫아야하는지 잘 모르겠습니다. :-(이 포럼에없는 경우 그러한 질문에 대한 답변을 어디에서 찾을 수 있습니까?

2
@Joe : 컴파일러가 어쨌든 말해 줄 때 무언가 컴파일 될지 찾기 위해 단위 테스트가 필요한 이유는 무엇입니까?
David Thornley

2
@David : 컴파일되지 않았 는지 확인하고 싶기 때문 입니다. 빠른 예는 입력을 받아들이고 출력 Pipeline<A,B>.connect(Pipeline<B,C>)을 컴파일하는 반면 Pipeline<A,B>.connect(Pipeline<C,D>)컴파일하지 않아야 하는 파이프 라인 객체 입니다. 첫 번째 스테이지의 출력 유형이 두 번째 스테이지의 입력 유형과 호환되지 않습니다.
sebastiangeiger

답변:


6

하나의 실행 파일에 모든 단위 테스트 (모듈)가 있습니다. 시험은 그룹으로 분류됩니다. 테스트 실행기의 명령 행에 (테스트 / 그룹) 이름을 지정하여 단일 테스트 (또는 일부 테스트) 또는 테스트 그룹을 실행할 수 있습니다. 빌드 시스템은 "Build"그룹을 실행할 수 있고 테스트 부서는 "All"을 실행할 수 있습니다. 개발자는 "BUG1234"와 같은 그룹에 몇 가지 테스트를 넣을 수 있으며 1234는 작업중인 사례의 이슈 트래커 번호입니다.


6

먼저 "1) (생산) 코드 및 단위 테스트 편집"에 동의하지 않습니다. 한 번에 하나만 수정해야합니다. 그렇지 않으면 결과가 변경되면 어떤 결과가 발생했는지 알 수 없습니다.

메인 트리를 가리는 디렉토리 트리에 단위 테스트를 넣고 싶습니다. 만약 내가 /sources/componentA/alpha/foo.cc하고 /objects/componentA/beta/foo.o, 그 다음 내가 좋아하는 뭔가를하고자 /UTest_sources/componentA/alpha/test_foo.cc하고 /UTest_objects/componentA/beta/test_foo.o. 스텁 / 모의 객체 및 테스트에 필요한 다른 소스에 동일한 섀도 트리를 사용합니다. 몇 가지 중요한 경우가 있지만이 체계는 일을 크게 단순화합니다. 훌륭한 편집기 매크로를 사용하면 테스트 소스를 손쉽게 대상 소스와 함께 가져올 수 있습니다. 좋은 빌드 시스템 (예 : GNUMake)은 두 가지를 모두 컴파일하고 하나의 명령으로 테스트를 실행할 수 있으며 (예 :) 마지막 make test_foo프로세스 이후 소스가 변경된 프로세스를 매우 쉽게 관리 할 수 ​​있습니다 (나는 가지고 있습니다) 이러한 프로세스를 시작하는 오버 헤드가 문제라는 것을 결코 발견하지 못했습니다. O (N)입니다.

동일한 프레임 워크에서 많은 개체를 연결하고 여러 테스트를 실행하는 더 큰 규모의 테스트 (더 이상 단위 테스트가 아님)를 가질 수 있습니다. 비결은 테스트를 빌드 / 실행하는 데 걸리는 시간을 기준으로 이러한 테스트를 정렬하고 그에 따라 일일 일정으로 테스트하는 것입니다. 필요할 때마다 1 초 이하의 테스트를 실행하십시오. 10 초 테스트를 시작하고 스트레칭; 5 분 동안 시험을보고 휴식을 취하십시오. 30 분 동안 시험을하고 점심을 먹습니다. 6 시간 동안 시험을보고 집으로 돌아갑니다. 작은 파일 하나만 변경 한 후 거대한 테스트를 다시 연결하는 등 많은 시간을 낭비하고있는 경우 연결이 즉각적인 경우에도 잘못된 테스트를 수행 할 수 있습니다. 요구되지 않았습니다.


ad (1)-그렇습니다. 어리석게 표현되었습니다
Martin Ba
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.