2021-01-19(Gtest 여덟 번째 예 포함)
아침
오늘 이 여덟 번째 예는 원리적으로 매우 간단하지만 그가 쓴 코드는 정말 무섭다. 뒤에 있는 이 코드들은 갈수록 무섭다고 말할 수 있지만 솔직히 나는 소프트웨어를 만드는 것도 아니고 80%도 쓸 수 없다.
Gtest 팁-9:'연합'매개 변수화 이전 두 절은 프로그램을 편리하게 하기 위해 매개 변수화할 때 각각 클래스, 바늘 변수를 매개 변수로 하여 서로 다른 방법으로 중복된 코드를 피했다. 는'연합'이라는 뜻으로 같은 테스트 수요를 가진 도구류를 합친 다음에 파라미터화 테스트를 할 때'파라미터 설정'(구체적으로 그런 방법으로 얼마나 측정하고 어떻게 측정하는가)을 전달하는 것을 말한다.그러나 이'전송 매개 변수'는 일반적으로 여러 종류가 있기 때문에 Combine()을 사용해야 한다. 구체적인 용법은 예시 코드를 참조한다.(하지만 일단 사용하면 도구류의 인터페이스를 모두 고쳐야 하기 때문에 우리의 테스트 수요에 비해 훨씬 쓸모가 없을 것 같다)
-----------------------------------------------------------------------------------------------------------
// This sample shows how to test code relying on some global flag variables.
// Combine() helps with generating all possible combinations of such flags,
// and each test is given one combination as a parameter.
// Use class definitions to test from this header.
#include "prime_tables.h"
#include "gtest/gtest.h"
namespace {
// Suppose we want to introduce a new, improved implementation of PrimeTable
// which combines speed of PrecalcPrimeTable and versatility of
// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
// appropriate under the circumstances. But in low memory conditions, it can be
// told to instantiate without PrecalcPrimeTable instance at all and use only
// OnTheFlyPrimeTable.
class HybridPrimeTable : public PrimeTable {
public:
HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
: on_the_fly_impl_(new OnTheFlyPrimeTable),
precalc_impl_(force_on_the_fly
? nullptr
: new PreCalculatedPrimeTable(max_precalculated)),
max_precalculated_(max_precalculated) {
}
~HybridPrimeTable() override {
delete on_the_fly_impl_;
delete precalc_impl_;
}
bool IsPrime(int n) const override {
if (precalc_impl_ != nullptr && n < max_precalculated_)
return precalc_impl_->IsPrime(n);
else
return on_the_fly_impl_->IsPrime(n);
}
int GetNextPrime(int p) const override {
int next_prime = -1;
if (precalc_impl_ != nullptr && p < max_precalculated_)
next_prime = precalc_impl_->GetNextPrime(p);
return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
}
private:
OnTheFlyPrimeTable* on_the_fly_impl_;
PreCalculatedPrimeTable* precalc_impl_;
int max_precalculated_;
};
using ::testing::TestWithParam;
using ::testing::Bool;
using ::testing::Values;
using ::testing::Combine;
// To test all code paths for HybridPrimeTable we must test it with numbers
// both within and outside PreCalculatedPrimeTable's capacity and also with
// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
// accept different combinations of parameters for instantiating a
// HybridPrimeTable instance.
class PrimeTableTest : public TestWithParam< ::std::tuple<bool, int> > {
protected:
void SetUp() override {
bool force_on_the_fly;
int max_precalculated;
std::tie(force_on_the_fly, max_precalculated) = GetParam();
table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
}
void TearDown() override {
delete table_;
table_ = nullptr;
}
HybridPrimeTable* table_;
};
TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
// Inside the test body, you can refer to the test parameter by GetParam().
// In this case, the test parameter is a PrimeTable interface pointer which
// we can use directly.
// Please note that you can also save it in the fixture's SetUp() method
// or constructor and use saved copy in the tests.
EXPECT_FALSE(table_->IsPrime(-5));
EXPECT_FALSE(table_->IsPrime(0));
EXPECT_FALSE(table_->IsPrime(1));
EXPECT_FALSE(table_->IsPrime(4));
EXPECT_FALSE(table_->IsPrime(6));
EXPECT_FALSE(table_->IsPrime(100));
}
TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
EXPECT_TRUE(table_->IsPrime(2));
EXPECT_TRUE(table_->IsPrime(3));
EXPECT_TRUE(table_->IsPrime(5));
EXPECT_TRUE(table_->IsPrime(7));
EXPECT_TRUE(table_->IsPrime(11));
EXPECT_TRUE(table_->IsPrime(131));
}
TEST_P(PrimeTableTest, CanGetNextPrime) {
EXPECT_EQ(2, table_->GetNextPrime(0));
EXPECT_EQ(3, table_->GetNextPrime(2));
EXPECT_EQ(5, table_->GetNextPrime(3));
EXPECT_EQ(7, table_->GetNextPrime(5));
EXPECT_EQ(11, table_->GetNextPrime(7));
EXPECT_EQ(131, table_->GetNextPrime(128));
}
// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of parameters. We must combine
// all variations of the boolean flag suppressing PrecalcPrimeTable and some
// meaningful values for tests. We choose a small value (1), and a value that
// will put some of the tested numbers beyond the capability of the
// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
// possible combinations.
INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest,
Combine(Bool(), Values(1, 10)));
} // namespace
그리고 글쓰기 연습하러 가자.전체적인 뜻은 기억할 수 있고 디테일은 잊어버린 것이 있다.
오후.
선생님의 말씀에 따라 코드를 쓰는 사고방식을 바꾸었다. 테스트부터 디자인하고'시스템'의 전체적인 사상으로 생각해 보니 확실히 큰 성과를 거두었다. 전체적인 사고방식이 달라졌다. 특히 인터페이스와 적용성을 최종 목적으로 할 때'기능 실현'을 위한 것이 아니다.원래는 정말 어리석었다. 생각한 대로 썼고 계획이 전혀 없었다. 재구성도 코드를 더 불필요하게 만들었을 뿐이고 그때 고칠 때 기분이 좋았다는 것이 믿기지 않았다. 마지막 계획은 지난달 흑하 디버깅을 할 때 다른api를 사용했을 때의 느낌에 따라 코드 디자인을 하는 것이다. 가장 뚜렷한 특징은
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
드래그텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.