单元测试之如何测试模板类

Ivy ·
更新时间:2024-09-21
· 706 次阅读

  一、背景   在搜狗内部对于C++项目进行单元测试,基本都是使用gtest进行的。无论是单元测试,还是接口测试我们都做了大量工作。   具体来说,是对函数进行单元测试或接口测试,对模块进行集成测试。但是,对于模板类并没有进行测试,而是对其上层调用进行测试。   现在的问题是,对于模板类需不需要进行单元测试或接口测试?被写成模板类,说明这个类是比较通用且很多地方都在使用它,所以我认为还是有必要进行测试的。   二、如何测试单参数模板类   下面直接进入主题:如何对单参数模板类进行测试?   有如下模板类 // 不用纠结于代码细节,只为说明 template <typename E> class Queue { public: Queue() {} void Enqueue(const E& element) {} E* Dequeue() {} size_t size() const { return (size_t)123; } };   那么使用gtest该如何对该类进行测试呢?   1、构建工厂类,用于创建被测试类   code   // 主模板类   template <class T>   Queue<T>* CreateQueue();   // 全特化版本1   template <>   Queue<int>* CreateQueue<int>()   {   return new Queue<int>;   }   // 全特化版本2   template <>   Queue<char>* CreateQueue<char>()   {   return new Queue<char>;   }   2、编写测试类   code   template <class T>   class QueueTest : public testing::Test   {   protected:   QueueTest() : queue(CreateQueue<T>())   {}   virtual ~QueueTest()   {   delete queue;   }   Queue<T>* const queue;   };   3、定义需要测试的类型   code   typedef testing::Types<int, char> Impls;   4、编写测试用例   code   TYPED_TEST_CASE(QueueTest, Impls);   TYPED_TEST(QueueTest, DefaultCons)   {   EXPECT_EQ(123, this->queue->size());   }5、运行用例,结果如下图

  温馨提醒   如果使用--gtest_filter进行过滤,则不能写为这样的形式:   --gtest_filter=QueueTest.DefaultCons   --gtest_filter=QueueTest.*   原因:因为后面带了 /n,n表示数字,需写为如下形式:   --gtest_filter=QueueTest*   在前面的例子中,被测试模板类只有一个类型参数,如果是多个类型参数呢,那该如何测试?   两个类型参数的模板类   // 如果有两个类型参数   template <class E, class F>   class Que   {   public:   Que() {}   void Enque(const E& el) {}   E* Deque() {}   F size() const   {   return (F)123;   }   };   大家可以静静的想几分钟,看能不能解决这个问题吧~~   三、如何测试多参数模板类   下面开始讨论这个主题:如何对多参数模板类进行测试?   不能照搬前面方案   当被测试模板类有两个甚至多个类型参数时,再按前面例子的办法来进行行不通了,因为gtest模板类测试宏仅接收一个模板参数,那该如何处理这个问题呢?   我的解决方案   将多个参数放在一个结构体里,做成一个模板类,将该模板类作为一个类型。   将多个参数组合成结构体   template <class A, class B>   struct Params   {   typedef typename A TypeA;   typedef typename B TypeB;   }   测试框架随之也要改变 template <class T> class TestX : public testing::Test { protected: TestX() : m_i(CreateIndex<typename T::TypeA, typename T::TypeB()) {} virtual ~TestX() { delete m_i; } void Setup() {} void TearDown() {} // Index为被测试模板类 Index<typename T::TypeA, typename T::TypeB>* const m_i; };   改变需要测试的类型列表的写法   typedef testing::Types<Params<int, int>, Params<char, char> > Impls;   测试用例书写方式也需要更改   TYPED_TEST_CASE(TestX, Impls);   TYPED_TEST(TestX, DefaultCons)   {   // 如果需要使用类型,需要写如下代码   typename TypeParam::TypeA sA;   typename TypeParam::TypeB sB;   ASSERT_EQ(0, this->m_i->length());   }



单元 测试模板 模板 单元测试 模板类 测试

需要 登录 后方可回复, 如果你还没有账号请 注册新账号