익명 네임 스페이스로 코드를 테스트 할 수 없음


12

일반적인 C ++ 코드는 다음과 같습니다.

foo.hpp

#pragma once

class Foo {
public:
  void f();
  void g();
  ...
};

foo.cpp

#include "foo.hpp"

namespace {
    const int kUpperX = 111;
    const int kAlternativeX = 222;

    bool match(int x) {
      return x < kUpperX || x == kAlternativeX;
    }
} // namespace

void Foo::f() {
  ...
  if (match(x)) return;
  ...

그것은 적절한 관용적 C ++ 코드처럼 보입니다-클래스, 그 도우미 함수에 match의해 사용되는 도우미 함수 Foo, 그 도우미 함수에 대한 상수.

그런 다음 테스트를 작성하고 싶습니다.
에 대한 별도의 단위 테스트를 작성하는 것이 완벽하게 논리적입니다 match. 왜냐하면 사소한 것이 아니기 때문입니다.
그러나 익명 네임 스페이스에 있습니다.
물론을 호출하는 테스트를 작성할 수 있습니다 Foo::f(). 그러나 Foo무겁고 복잡한 경우 좋은 시험이되지 않을 것입니다. 이러한 시험은 피검사자를 다른 관련없는 요소와 격리시키지 않습니다.

따라서 match익명 네임 스페이스에서 다른 모든 것을 옮겨야 합니다.

질문 : 함수와 상수를 테스트에서 사용할 수 없게 만드는 익명 네임 스페이스에 넣는 점은 무엇입니까?


3
@ BЈовић 코드를 다시 읽으십시오 – 익명 네임 스페이스는 foo.cpp헤더가 아니라에 있습니다! OP는 헤더에 네임 스페이스를 넣지 말아야한다는 것을 잘 이해하는 것 같습니다.
amon

명명되지 않은 네임 스페이스에서 C ++ 코드를 테스트 하는 단위에 대한 몇 가지 아이디어 가 있습니다. 결국 그것은 개인 멤버 함수와 동일한 문제입니다 : 그것들은 방해하지 않고 테스트 할 수는 없지만 단위 테스트를 위해 정보 숨기기를 포기하고 싶지 않습니다 (예 : stackoverflow.com/a/3676680/3235496 ).
manlio

1
개인의 방법을 테스트하거나 테스트하지 않는 경우와 개념이 크게 다르지 않습니다. 따라서 프로그래머에서 "unit test private"을 검색하면 사례에 직접 적용 할 수있는 많은 답변을 얻을 수 있습니다.
Doc Brown

@DocBrown 나는 함수를 테스트하는 방법을 묻지 않았다. 네임 스페이스. "왜 anon. 네임 스페이스에 코드를 넣을까요?" (질문 끝에있는 텍스트 참조). 제목을 다른 것으로 변경 한 것에 대한 Blame Ixrec.
Abyx

2
@Abyx : 위에서 언급 한 다른 답변에서 개인 방법을 테스트하는 것은 좋지 않은 아이디어 friend이며 해당 목적을 위해 키워드를 남용하는 것은 권장되지 않는다는 많은 전문가들의 큰 합의를 찾을 수 있습니다. 메소드에 대한 제한으로 인해 더 이상 직접 테스트 할 수없는 상황이 발생하면 개인 메소드가 유용하지 않은 것입니다.
Doc Brown

답변:


7

개인 구현 세부 사항을 단위 테스트하려면 개인 (또는 보호 된) 클래스 멤버와 같은 이름없는 네임 스페이스에 대해 동일한 종류의 닷지를 수행하십시오.

침입하고 파티하십시오.

당신이 남용하는 클래스의 경우 friend, 이름없는 네임 스페이스의 경우- #include메커니즘 을 남용 하므로 코드를 변경하지 않아도됩니다.
이제 테스트 코드 (또는 모든 것을 노출시키는 것이 더 좋습니다)가 동일한 TU에 있으므로 문제가 없습니다.

주의 사항 : 구현 세부 사항을 테스트하면 변경 사항이 있으면 테스트가 중단됩니다. 어쨌든 누출 될 구현 세부 사항 만 테스트하거나 테스트가 비정상적으로 일어남을 수락하십시오.


6

예제의 함수는 매우 복잡해 보이며 단위 테스트를 위해 헤더로 이동하는 것이 좋습니다.

테스트에서 사용할 수없는 함수와 상수를 익명 네임 스페이스에 넣는 요점은 무엇입니까?

세계의 다른 지역과 격리시키기 위해. 익명 네임 스페이스에 넣을 수있는 것은 함수와 상수 일뿐만 아니라 형식도 마찬가지입니다.

그러나 단위 테스트가 매우 복잡해지면 잘못하고 있습니다. 이 경우 해당 기능은 해당되지 않습니다. 그런 다음 리팩토링을 조금만하면 테스트가 간단 해집니다.

따라서 익명 네임 스페이스에서는 매우 간단한 함수, 때로는 해당 변환 단위에 사용되는 상수 및 유형 (typedef 포함) 만 사용해야합니다.


5

사소한 것이 아니기 때문에 별도의 단위 테스트를 작성하는 것이 완벽하게 논리적입니다.

당신이 보여준 코드 match는 까다로운 가장자리가없는 아주 간단한 1 라이너입니까, 아니면 간단한 예제입니까? 어쨌든 단순화 된 것으로 가정합니다 ...

질문 : 함수와 상수를 테스트에서 사용할 수 없게 만드는 익명 네임 스페이스에 넣는 점은 무엇입니까?

이 질문은 Deduplicator가 이미 #include속임수를 통해 접근 할 수있는 완벽한 방법을 보여 주었기 때문에 여기서 뛰어 들고 싶었던 것 입니다. 그러나 여기서 말하는 것은 모든 내부 구현 세부 사항을 테스트하는 것처럼 들리는데, 그것이 멀어 질 때 보편적 인 최종 목표입니다.

단위 테스트의 목표는 모든 작은 단위의 내부 미세 단위 기능을 항상 테스트하는 것이 아닙니다. 개발자가 사용하는 이유 같은 질문을 물어도 대답에 질문 어렵게 만들 수 있습니다 C. 당신의 정적 파일 범위의 기능에 적용 pimpls필요로하는 C ++로 모두 friendship#include개선 된 컴파일 시간에 대한 구현 세부 사항을 쉽게 테스트 용이성을 거래, 흰색 상자에 속임수를, 예 :

실용적 관점에서 볼 때 그것은 거칠게 들릴 수도 있지만, match트립이 발생하는 일부 경우에는 올바르게 구현되지 않을 수 있습니다. 그러나 Foo액세스 할 match수 있는 유일한 외부 클래스 가 이러한 엣지 케이스와 마주 치는 방식으로 사용할 수없는 경우 변경이 없으면 절대 오지 않는 엣지 케이스가 있는 정확성과 Foo는 관련 match이 없습니다. Foo의 테스트 Foo는 실패하고 우리는 즉시 알게 될 것입니다.

모든 단일 내부 구현 세부 사항 (예 : 미션 크리티컬 소프트웨어 등)을 테스트하려는 열망적인 사고 방식은 침입하기를 원할 수 있지만 많은 사람들이 이것이 최상의 아이디어라고 생각할 필요는 없습니다. 상상할 수있는 대부분의 취성 테스트. YMMV. 그러나 나는이 질문에 대한 말을하고 싶었습니다.이 엄밀한 내부 세부 정보 수준의 테스트 가능성은 최종 목표가되어야한다고 생각합니다. 가장 엄격한 단위 테스트 마인드조차도 여기서 조금 긴장을 풀 수 있습니다. 모든 클래스의 내부를 엑스레이하지 마십시오.

그렇다면 왜 사람들은 C ++에서 익명 네임 스페이스의 함수를 정의하거나 외부 세계에서 숨겨진 C의 내부 링크를 가진 파일 범위 정적 함수로 정의합니까? 그리고 그것은 주로 외부 세계에서 그들을 숨기는 것입니다. 이는 컴파일 시간 단축부터 복잡성 감소 (다른 곳에서는 액세스 할 수없는 것 등)에서 여러 가지 영향을 미칩니다. 아마도 개인 / 내부 구현 세부 사항에 대한 테스트 가능성은 사람들이 생각할 때 가장 중요한 것은 아닙니다. 즉, 빌드 시간을 줄이고 외부 세계에서 불필요한 복잡성을 숨 깁니다.


나는 이것을 10 번 공표 할 수 있기를 바란다. 미션 크리티컬, 높은 보증 소프트웨어와 관련된 접선으로서, 세부 사항의 정확성에 훨씬 더 관심이 있습니다. C ++에 대한이 관용적 스타일은 적합하지 않습니다. 익명 네임 스페이스 나 프록시와 같은 패턴과 같은 언어 기능을 사용하지 않습니다. [지원되는] 사용자 공간 헤더 및 [지원되지 않는] 개발자 공간 헤더를 사용하여 경계를 거칠게 제어합니다.
David
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.