문제

단위 테스트를 위해 네트워크 응답을 모형화해야 합니다.응답은 일반적으로 바이트 스트림으로 저장됩니다. const vector<uint8_t>.그러나 단위 테스트의 경우 CPP 파일에 하드코딩되거나 동일한 솔루션의 파일에서 읽은 데이터로 벡터를 생성하고 싶습니다.내 예제 데이터는 약 6kb입니다.사용할 때 데이터를 배치할 위치에 대한 일반적인 지침은 무엇입니까? 구글테스트?

도움이 되었습니까?

해결책

아마도 (a) 테스트 사례가 읽을 수있는 일부 역할에 대해서는 큰 데이터 시퀀스가 ​​필요합니다.이는 (클래스) 전역 데이터일 수도 있습니다.const 입장.

아마도 (b) 테스트 사례가이를 읽고 수정하거나 파괴 할 수있는 일부 역할에 대해서는 대량의 데이터가 필요합니다.이것은 다음과 같아야 합니다. 테스트 케이스당 초기화되고const 입장.

아마도 둘 다일 것입니다.두 경우 모두 기존의 googletest 구현은 사용 테스트 픽스처 데이터 수집을 캡슐화하려면 조명기의 가상 구현 Setup() member 함수 및 픽스처의 getter 메소드를 통해 액세스하십시오.

다음 프로그램은 케이스별 두 가지를 모두 제공하는 픽스처를 보여줍니다. 변경 가능한 데이터 및 파일에서 얻은 전역 상수 데이터.

#include <vector>
#include <fstream>
#include <stdexcept>
#include "gtest/gtest.h"

class foo_test : public ::testing::Test
{
protected:
    virtual void SetUp() {
        std::ifstream in("path/to/case_data");
        if (!in) {
            throw std::runtime_error("Could not open \"path/to/case_data\" for input");
        }
        _case_data.assign(
            std::istream_iterator<char>(in),std::istream_iterator<char>());
        if (_global_data.empty()) {
            std::ifstream in("path/to/global_data");
            if (!in) {
                throw std::runtime_error(
                    "Could not open \"path/to/global_data\" for input");
            }
            _global_data.assign(
                std::istream_iterator<char>(in),std::istream_iterator<char>());
        }
    }
    // virtual void TearDown() {}   
    std::vector<char> & case_data() {
        return _case_data;
    }
    static std::vector<char> const & global_data() {
        return _global_data;
    }

private:
    std::vector<char> _case_data;
    static std::vector<char> _global_data;

};

std::vector<char> foo_test::_global_data;

TEST_F(foo_test, CaseDataWipe) {
  EXPECT_GT(case_data().size(),0);
  case_data().resize(0);
  EXPECT_EQ(case_data().size(),0);
}

TEST_F(foo_test, CaseDataTrunc) {
  EXPECT_GT(case_data().size(),0);
  case_data().resize(1);
  EXPECT_EQ(case_data().size(),1);
}

TEST_F(foo_test, HaveGlobalData) {
  EXPECT_GT(global_data().size(),0);
}


int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

(a)의 경우, 다음과 같은 방법으로 데이터를 수집하는 것도 고려할 수 있습니다. 글로벌 설정서브클래싱을 통한 멤버 함수 ::testing::Environment, 하지만 나는 못한다 그런 식으로하는 것을 선호하는 일반적인 이유.

...아니면 하드 코딩할까요?

그런 다음 테스트 데이터를 파일에 보관할지 아니면 하드 코드로 유지할지 여부에 대한 문제입니다 테스트 소스에 있습니다. 지금 이 순간이 행복한 독자들은 이제부터 지루할 뿐이다..

일반적인 문제로서 이것은 상황에 따른 판단의 문제이며 나는 생각하지 않습니다 googletest의 사용은 저울을 실질적으로 기울입니다.가장 중요한 고려 사항이라고 생각합니다 다음과 같습니다. 테스트 방송을 재건하지 않고 테스트 데이터 항목을 변경하는 것이 바람직합니까?

이 항목을 변경하기 위해 테스트 스위트를 다시 빌드하는 것은 무시할 수 없는 비용이며 항목의 내용이 향후 독립적으로 달라질 것으로 예상합니다. 관련 테스트 코드의.또는 관련 테스트 코드와 독립적으로 다를 수 있습니다. 테스트 중인 시스템의 다양한 구성에 대해.이 경우 가장 좋은 런타임 매개변수로 선택할 수 있는 파일 또는 다른 소스의 항목 테스트 도구 모음입니다.googletest에서 서브클래싱 class ::testing::Environment 는 테스트 스위트 리소스의 파라미터화된 수집을 위한 설계된 시설.

만약에 실제로는 테스트 데이터 항목의 내용은 다음과 느슨하게 결합됩니다. 관련 테스트 코드를 테스트 케이스에 하드 코딩하는 것은 거의 불가능합니다 신중한 선택이 될 수 있습니다.(그리고 다른 종류의 런타임과 달리 테스트 파일 구성기에는 버전 제어가 가능한 중요한 속성이 있습니다. 소스 코드와 동일한 시스템.)

테스트 데이터 항목의 내용인 경우 ~이다 단단히 결합 된 관련 테스트 코드를 추출하기보다는 하드 코딩하는 것이 편향되어 있습니다. 데이터 파일에서.단지 편견이 있을 뿐, 독단적으로 헌신하지는 않습니다.어쩌면 당신의 테스트 suite는 공개 API 테스트 데이터를 초기화하기 위해 강력한 라이브러리 기능을 사용합니다. 예를 들어, 테스트 관리 및 결함 관리에도 연결된 XML 파일, 시스템.괜찮은!

테스트 데이터 파일이 기본 인 경우 분명히 바람직하다고 생각합니다. 테스트 리소스 - 테스트 스위트가 생성할 수 없는 리소스 - 그 내용 유능한 관리자가 쉽게 이해할 수 있는 텍스트 데이터가 가장 좋습니다. 그리고 조작합니다.이 설정에서 나는 물론 예를 들어, C/C++ 16진수 상수 목록은 다음과 같습니다. 텍스트 데이터 -그것이 소스 코드.테스트 파일에 바이너리 또는 매우 기계 지향적인 데이터가 포함된 경우 그런 다음 테스트 스위트는 읽을 수 있는 생산 수단을 가장 잘 포함해야 합니다. 기본 리소스.테스트 스위트가 의존하는 것이 불가피한 경우가 있습니다 외부에서 공급되는 "원형" 바이너리이지만 거의 필연적으로 테스트 엔지니어와 버그 수정자가 육각 편집자 앞에서 회색으로 변하는 음산한 광경.

1차 테스트 데이터는 메인테이너가 읽을 수 있어야 한다는 원칙을 감안할 때, 기본 테스트 데이터가 "일종의 코드"가 될 것이라는 규범으로 간주 할 수 있습니다.그것은 것이다 논리가 자유롭지만 프로그래머가 하는 일종의 텍스트 자료가 될 것입니다. 측량 및 편집에 익숙합니다.

4096 64 비트 부호없는 정수의 특정 시퀀스를 상상해보십시오. (Big Magic Table)은 소프트웨어를 테스트하는 데 필요하며 관련 테스트 코드에 결합됩니다.거대한 벡터 또는 배열로 하드 코딩 될 수 있습니다 테스트 스위트의 일부 소스 파일에 있는 이니셜라이저 목록입니다.그럴 수 있습니다 CSV 형식 또는 CSV 구두점 줄.

데이터 파일에서 추출하고 하드 코딩에 대해 촉구할 수 있습니다. (앤드류 맥도넬 (Andrew McDonell)의 대답에 따르면) 이것은 가치있게 엉킴을 풀어줍니다. 동일한 코드의 다른 코드 개정에서 BMT에 대한 개정 소스 파일.마찬가지로, 프레임을 구성하는 모든 소스 코드가 거대한 리터럴 초기화는 조사 할 수없는 경향이 있으므로 유지 보수가 필요합니다 책임.

그러나 이 두 가지 점은 모두 다음과 같은 관찰로 반박될 수 있습니다. BMT의 선언은 자체 소스 파일에 코딩될 수 있습니다.술래 데이터 초기화를 테스트하는 테스트 도구 모음에 대한 코드 검토 정책일 수 있습니다. ~ 해야 하다 그렇게 코딩 될 수 있습니다 - 그리고 아마도 독특한 이름을 고수하는 파일에 있습니다. 컨벤션.확실히 광신적인 정책이지만 그보다 더 광신적이지는 않습니다 모든 테스트 데이터 이니셜 라이저를 파일에서 추출해야한다고 주장하는 것입니다.메인테이너가 BMT가 포함된 파일에서 BMT를 조사해야 하는 경우, 파일 확장자가 있는지 여부는 차이가 없습니다. .cpp, .dat 또는 것은 무엇이든지:모든 문제는 "코드"의 이해도입니다.

하드 코딩 및 데이터 파일에서 추출에 반대하는 경우 촉구할 수 있습니다. 데이터 파일에서 추출하면 관련 없는 소스가 도입되어야 합니다. 테스트 케이스에 대한 잠재적 실패 - 모든 일어나지 말아야 할 일 오류 파일에서 올바른 데이터를 읽지 못할 수 있습니다.이것은 오버헤드를 부과합니다. 실제 테스트 실패와 실제 테스트 실패를 정확하고 명확하게 구분하기 위한 테스트 개발 파일에서 테스트 데이터를 수집하지 못하고 가능한 모든 것을 명확하게 진단하지 못함 후자의 원인.

googletest와 비교적 기능적인 프레임 워크의 경우이 점은 다음과 같을 수 있습니다. 어느 정도는 다형성 픽스처 기본 클래스에 광고함으로써 대응했습니다 같이 ::testing::Test 그리고 ::testing::Environment.이것들은 촉진합니다 테스트 케이스에서 테스트 리소스 획득을 캡슐화하는 테스트 개발자 또는 테스트 스위트 초기화를 수행하여 모든 것이 성공적으로 끝나거나 테스트 케이스의 구성 요소 테스트가 실행되기 전에 진단된 실패가 있는 경우.RAII는 설정 실패와 실제 실패 사이를 문제 없이 구분할 수 있습니다.

그럼에도 불구하고 데이터 파일에 대한 줄일 수 없는 파일 처리 오버헤드가 있습니다 경로 그리고 RAII가 프레임워크의 기능을 제공하는 운영 오버헤드가 있습니다. 줄이기 위해 아무 것도 하지 마십시오.거래되는 무거운 테스트 시스템을 다룰 때 데이터 파일, 데이터 파일 그냥 운영 사고가 발생하기 쉬움 빌드 시 존재하고 수정하기만 하면 되는 소스 파일입니다.데이터 파일이 런타임 중에 누락되거나 잘못 배치될 가능성이 더 높습니다. 잘못된 형식의 내용을 포함하거나 어떻게 든 허가가 거부되었습니다. 어쨌든 잘못된 개정판에 나타납니다.테스트 시스템에서의 사용 소스 파일만큼 간단하거나 엄격하게 제어되지 않습니다. 일어나지 말아야 할 일 테스트 데이터 파일은 운영 마찰의 일부입니다. 그것들에 의존하고 그 수에 비례하는 테스트 시스템.

부터 소스 파일 테스트 데이터 초기화를 위생적으로 캡슐화할 수 있습니다. 개정 추적의 경우 하드 코딩은 파일, 전처리기가 컴파일의 부산물로 추출을 수행합니다.그렇다면 추가 책임을 안고 다른 기계를 사용하여 추출할 이유가 무엇입니까?테스트 관리와 함께 제안 된 XML 인터페이스와 같은 좋은 대답이있을 수 있습니다. 결함 관리 시스템이지만 "테스트 데이터이므로 하드 코딩하지 마십시오"는 좋은 시스템이 아닙니다.

테스트 스위트가 아래의 다양한 시스템 구성을 지원해야 하는 경우에도 테스트 데이터 항목의 다양한 인스턴스화를 호출하는 테스트(데이터가 item은 다음과 불변입니다. 테스트 스위트의 빌드 구성, 당신은 다음과 같이 할 수 있습니다 글쎄, 여전히 (위생적으로) 하드 코딩하고 조건부 컴파일을 선택하도록하십시오. 올바른 하드 코딩.

지금까지 나는 revision-tracking-hygeine 논쟁에 도전하지 않았다 테스트 데이터 이니셜라이저의 파일 기반 분리용.방금 만들었습니다. 이니셜 라이저가 하드 코딩 된 일반 소스 파일이 이 분리를 수행합니다.그리고 나는 그 논쟁을 짓밟고 싶지 않지만, 나는 데이터 이니셜 라이저를 테스트한다는 광신적인 결론에 미치지 못하게하고 싶다. 원칙적으로 항상 전용 파일에서 추출해야 합니다. 소스 파일 또는 데이터 파일인지 여부.

이 결론에 반대하는 이유를 자세히 설명할 필요는 없습니다.그와 같이 로컬에있는 테스트 코드를 거짓말합니다. 더 적은 평균적인 피자 먹는 것보다 이해할 수 있습니다. 프로그래머는 성장하는 테스트 스위트 파일을 작성하고 구성합니다. 필요하거나 건강한 것보다 훨씬 더 빨리 정신을 차리게 됩니다.규범적으로, 테스트 스위트의 모든 기본 리소스는 "일종의 코드"입니다.A 프로그래머의 기술에는 코드를 파일로 분할하는 기술이 포함됩니다 적절한 개정 추적 위생을 확보하기 위해 적절한 세분성으로.코드 검토에서 다루는 것은 기계적인 절차가 아니라 전문 지식입니다.그러나 코드 검토는 테스트 데이터 초기화를 보장할 수 있고 보장해야 합니다. 그것들은 성취되고, 개정 추적에 대해 잘 설계되고 제작되었습니다 다른 모든 일상적인 측면에서와 마찬가지로.

요점:다양한 테스트 스위트의 동일한 빌드를 실행할 수 있기를 원한다면 이러한 모의 신경망 응답 중 파일에서 읽어 들입니다.반면에 테스트 스위트의 빌드 구성과 불변 또는 공변입니다. 왜 안 돼 힘들다 코드를 작성하시겠습니까?

다른 팁

(Caveat -이 대답은 모든 단위 테스트 프레임 워크에서 일반적입니다)

Revision Control 시스템에서 데이터 파일을 별도의 객체로 유지하는 것을 선호합니다.이것은 다음과 같은 이점을 제공합니다 :

  • 다양한 상황을 테스트하기 위해 모든 또는 여러 데이터 파일을 수락하는 장치 테스트를 코딩 할 수 있습니다.
  • 필요에 따라 데이터의 변경 사항을 추적 할 수 있습니다

단위 테스트 실행이 일부 상황에서 필요한 조건이 될 수있는 데이터 파일을 읽지 않으려면 조명기 설정에서 벡터를 초기화하는 C ++ 코드를 생성하는 프로그램이나 스크립트를 작성하도록 선택할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top