Google单元测试框架gtest之官方sample笔记2--类型参数测试
gtest 提供了类型参数化测试方案,可以测试不同类型的数据接口,比如模板测试。可以定义参数类型列表,按照列表定义的类型,每个测试case都执行一遍。
本例中,定义了2种计算素数的类,一个是实时计算,一个是提前计算好存放到一个大数组了。既空间和时间实现方式的对比。两种实现类都继承于抽象类PrimeTable。
- // The prime table interface.
- class PrimeTable {
- public:
- virtual ~PrimeTable() {}
-
- // Returns true if and only if n is a prime number.
- virtual bool IsPrime(int n) const = 0;
-
- // Returns the smallest prime number greater than p; or returns -1
- // if the next prime is beyond the capacity of the table.
- virtual int GetNextPrime(int p) const = 0;
- };
为了测试,定义了一个测试类,使用了两种特例化的CreatePrimeTable模板函数。
- template <class T>
- PrimeTable* CreatePrimeTable();
- template <>
- PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
- return new OnTheFlyPrimeTable;
- }
- template <>
- PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
- return new PreCalculatedPrimeTable(10000);
- }
- // Then we define a test fixture class template.
- template <class T>
- class PrimeTableTest : public testing::Test {
- protected:
- // The ctor calls the factory function to create a prime table
- // implemented by T.
- PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
-
- ~PrimeTableTest() override { delete table_; }
-
- // Note that we test an implementation via the base interface
- // instead of the actual implementation class. This is important
- // for keeping the tests close to the real world scenario, where the
- // implementation is invoked via the base interface. It avoids
- // got-yas where the implementation class has a method that shadows
- // a method with the same name (but slightly different argument
- // types) in the base interface, for example.
- PrimeTable* const table_;
- };
具体测试,有3个测试用例.
- TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes)
- TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes)
- TYPED_TEST(PrimeTableTest, CanGetNextPrime)
sample 6也演示了两种模式,第一种模式是已知所有的类型,先定义为一个Types结构。
- typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
- #define TYPED_TEST_SUITE TYPED_TEST_CASE
-
- TYPED_TEST_SUITE(PrimeTableTest, Implementations);
第二种模式,不知道具体的类型,在运行测试时候,动态的绑定新的类型到测试fixture。
- TYPED_TEST_SUITE_P(PrimeTableTest2);
-
- REGISTER_TYPED_TEST_SUITE_P(
- PrimeTableTest2, // The first argument is the test case name.
- // The rest of the arguments are the test names.
- ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
-
-
- typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
- PrimeTableImplementations;
-
- INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated, // Instance name
- PrimeTableTest2, // Test case name
- PrimeTableImplementations); // Type list
测试结果如下图,PrimeTableTest有2个类型,3个案例。PrimeTableTest2也有2个类型,3个案例。合计运行了12个tests。
代码分析
这个例子非常复杂,分析下主要的函数的调用。
第一步:定义Types
typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
- // Types 的定义为:
- template <typename T1, typename T2>
- struct Types<T1, T2, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types2<T1, T2> type;
- };
第二步:定义测试套件(Test suite)
TYPED_TEST_SUITE(PrimeTableTest, Implementations);
- // TYPED_TEST_SUITE 在老版本里叫做TYPED_TEST_CASE, 定义为
- # define TYPED_TEST_CASE(CaseName, Types, ...) \
- typedef ::testing::internal::TypeList< Types >::type GTEST_TYPE_PARAMS_( \
- CaseName); \
- typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
- GTEST_NAME_GENERATOR_(CaseName)
GTEST_TYPE_PARAMS、GTEST_NAME_GENERATOR_、NameGeneratorSelector依赖于:
- // GTEST_TYPE_PARAMS
- # define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
- // GTEST_NAME_GENERATOR_
- #define GTEST_NAME_GENERATOR_(TestCaseName) \
- gtest_type_params_##TestCaseName##_NameGenerator
-
- struct DefaultNameGenerator {
- template <typename T>
- static std::string GetName(int i) {
- return StreamableToString(i);
- }
- };
- // NameGeneratorSelector
- template <typename Provided = DefaultNameGenerator>
- struct NameGeneratorSelector {
- typedef Provided type;
- };
TYPED_TEST_SUITE(PrimeTableTest, Implementations) 用上面的宏替换后:
- typedef::testing::internal::TypeList<Implementations>::type gtest_type_params_PrimeTableTest_;
- typedef ::testing::internal::__VA_ARGS__ gtest_type_params_PrimeTableTest_NameGenerator
- //TypeList 扩展
- template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48, typename T49, typename T50>
- struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47, T48, T49, T50> > {
- typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
- };
-
- // TypeList的type是 Types::type的别名,2个模板参数的Types::type是Types2类型,所以进一步扩展为:
- struct testing::internal::Types2<class OnTheFlyPrimeTable,class PreCalculatedPrimeTable> gtest_type_params_PrimeTableTest_;
- // NameGeneratorSelector<__VA_ARGS__>::type 类型返回Provided类型参数,默认为DefaultNameGenerator类型
- struct testing::internal::DefaultNameGenerator gtest_type_params_PrimeTableTest_NameGenerator
第三步:定义测试case,case名字要和test fixture名字相同。
- // Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
- // similar to TEST_F.
- TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
- // Inside the test body, you can refer to the type parameter by
- // TypeParam, and refer to the fixture class by TestFixture. We
- // don't need them in this example.
-
- // Since we are in the template world, C++ requires explicitly
- // writing 'this->' when referring to members of the fixture class.
- // This is something you have to learn to live with.
- EXPECT_FALSE(this->table_->IsPrime(-5));
- EXPECT_FALSE(this->table_->IsPrime(0));
- EXPECT_FALSE(this->table_->IsPrime(1));
- EXPECT_FALSE(this->table_->IsPrime(4));
- EXPECT_FALSE(this->table_->IsPrime(6));
- EXPECT_FALSE(this->table_->IsPrime(100));
- }
-
- TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
- EXPECT_TRUE(this->table_->IsPrime(2));
- EXPECT_TRUE(this->table_->IsPrime(3));
- EXPECT_TRUE(this->table_->IsPrime(5));
- EXPECT_TRUE(this->table_->IsPrime(7));
- EXPECT_TRUE(this->table_->IsPrime(11));
- EXPECT_TRUE(this->table_->IsPrime(131));
- }
-
- TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
- EXPECT_EQ(2, this->table_->GetNextPrime(0));
- EXPECT_EQ(3, this->table_->GetNextPrime(2));
- EXPECT_EQ(5, this->table_->GetNextPrime(3));
- EXPECT_EQ(7, this->table_->GetNextPrime(5));
- EXPECT_EQ(11, this->table_->GetNextPrime(7));
- EXPECT_EQ(131, this->table_->GetNextPrime(128));
- }
TYPED_TEST是个宏定义,展开为:
- # define TYPED_TEST(CaseName, TestName) \
- template <typename gtest_TypeParam_> \
- class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
- : public CaseName<gtest_TypeParam_> { \
- private: \
- typedef CaseName<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- virtual void TestBody(); \
- };
-
- #define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
- test_case_name##_##test_name##_Test
TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) 替换掉宏后为:
- template <typename gtest_TypeParam_> \
- class PrimeTableTest_ReturnsFalseForNonPrimes_Test \
- : public PrimeTableTest<gtest_TypeParam_> { \
- private: \
- typedef PrimeTableTest<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- virtual void TestBody(); \
- };
EXPECT_FALSE(this->table_->IsPrime(-5)) 展开如下,使用AssertionResult函数判断是否为true。
- // 定义
- #define EXPECT_FALSE(condition) \
- GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
- GTEST_NONFATAL_FAILURE_)
-
- #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const ::testing::AssertionResult gtest_ar_ = \
- ::testing::AssertionResult(expression)) \
- ; \
- else \
- fail(::testing::internal::GetBoolAssertionFailureMessage(\
- gtest_ar_, text, #actual, #expected).c_str())
- // 展开为
- #define EXPECT_FALSE(condition) \
- if (const ::testing::AssertionResult gtest_ar_ = ::testing::AssertionResult(condition)) ; \
- else fail(::testing::internal::GetBoolAssertionFailureMessage(gtest_ar_, #condition, "true", "false").c_str())
具体的函数执行,启动test用例,TestBody()虚函数是入口。
尊重技术文章,转载请注明!
Google单元测试框架gtest之官方sample笔记2--类型参数测试
Google单元测试框架gtest之官方sample笔记2--类型参数测试的更多相关文章
- Google单元测试框架gtest之官方sample笔记3--值参数化测试
1.7 sample7--接口测试 值参数不限定类型,也可以是类的引用,这就可以实现对类接口的测试,一个基类可以有多个继承类,那么可以测试不同的子类功能,但是只需要写一个测试用例,然后使用参数列表实现 ...
- Google单元测试框架gtest之官方sample笔记4--事件监控之内存泄漏测试
sample 10 使用event listener监控Water类的创建和销毁.在Water类中,有一个静态变量allocated,创建一次值加一,销毁一次值减一.为了实现这个功能,重载了new和d ...
- Google单元测试框架gtest之官方sample笔记1--简单用例
1.0 通用部分 和常见的测试工具一样,gtest提供了单体测试常见的工具和组件.比如判断各种类型的值相等,大于,小于等,管理多个测试的测试组如testsuit下辖testcase,为了方便处理初始化 ...
- Google单元测试框架gtest--值参数测试
测试一个方法,需要较多个参数进行测试,比如最大值.最小值.异常值和正常值.这中间会有较多重复代码工作,而值参数测试就是避免这种重复性工作,并且不会损失测试的便利性和准确性. 如果测试一个函数,需要些各 ...
- C++单元测试框架gtest使用
作用 作为代码编码人员,写完代码,不仅要保证编译通过和运行,还要保证逻辑尽量正确.单元测试是对软件可测试最小单元的检查和校验.单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成 ...
- 简单易懂的单元测试框架-gtest(一)
简介 gtest是google开源的一个单元测试框架,以其简单易学的特点被广泛使用.该框架以第三方库的方式插入被测代码中.同其他单元测试框架相似,gtest也通过制作测试样例来进行代码测试.同 ...
- Google C++单元测试框架---Gtest框架简介(译文)
一.设置一个新的测试项目 在用google test写测试项目之前,需要先编译gtest到library库并将测试与其链接.我们为一些流行的构建系统提供了构建文件: msvc/ for Visual ...
- 简单易懂的单元测试框架-gtest(二)
简介 事件机制用于在案例运行前后添加一些操作(相当于挂钩函数).目前,gtest提供了三种等级的事件,分别: 全局级,所有案例执行的前后 TestSuite级,某一个案例集的前后 TestCa ...
- Google C++单元测试框架GoogleTest---GTest的Sample1和编写单元测试的步骤
如果你还没有搭建gtest框架,可以参考我之前的博客:http://www.cnblogs.com/jycboy/p/6001153.html.. 1.The first sample: sample ...
随机推荐
- Think in Java 第四 五 章
Think in Java 第四章 控制执行流程 测试while public class whileTest { static boolean condition(){ boolean result ...
- 2019牛客暑期多校训练营(第九场)J Symmetrical Painting (思维)
传送门 大体思路就是:枚举所有可能的水平对称线,计算面积更新答案. 所有可能的水平对称线:\(L_i,R_i,{L_i+R_i\over 2}\) 计算面积:将所有可能的水平对称线从小到大排序,然后依 ...
- HDOJ1232 畅通工程 DFS
很早之前就做过的题以前用并查集做的 现在用DFS重做算是熟悉DFS吧 #include<stdio.h>#include<string.h>const int size=100 ...
- cf-1230C Anadi and Domino
题目链接:http://codeforces.com/contest/1230/problem/C 题意: 有21 个多米诺骨牌,给定一个无向图(无自环,无重边),一条边上可以放一个多米诺骨牌.如果两 ...
- Codeforces Round #672 (Div. 2) C1. Pokémon Army (easy version) (DP)
题意:给你一组数\(a\),构造一个它的子序列\(b\),然后再求\(b_1-b2+b3-b4...\),问构造后的结果最大是多少. 题解:线性DP.我们用\(dp1[i]\)来表示在\(i\)位置, ...
- Docker文件挂载总结
Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定. 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定: # docker ...
- HDU 4049 Tourism Planning(状压DP)题解
题意:m个城市,n个人,让这n个人按固定顺序走遍m个城市.每个城市有一个单人票价pi.每个人在每个城市能获得vij的价值.如果多个人在同一城市,那么会额外获得价值,给出一张n * n价值表,额外价值为 ...
- Google coding Style Guide : Google 编码风格/代码风格 手册/指南
1 1 1 https://github.com/google/styleguide Google 编码风格/代码风格 手册/指南 Style guides for Google-originated ...
- CSS 定位 relative && absolute 问题?
1 1 1 CSS 定位 relative && absolute 问题? 谁能解释一下,为什么div使用 relative是设置right,bottom 后,看不到div 呀,哪里多 ...
- javascript change array length methods
javascript change array length methods Array 改变数组长度的方法 push, pop shift, unshift, splice, fill, 不改变数组 ...