程序员人生 网站导航

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

栏目:php教程时间:2015-06-27 07:44:11

1、背景


在搜狗内部对C++项目进行单元测试,基本都是使用gtest进行的。不管是单元测试,还是接口测试我们都做了大量工作。

具体来讲,就是对函数进行单元测试或接口测试,对模块进行集成测试。但是,对模板类并没有进行测试,而是对其上层调用进行测试。

现在的问题是,对模板类需不需要进行单元测试或接口测试?被写成模板类,说明这个类是比较通用且很多地方都在使用它,所以我认为还是有必要进行测试的。


2、如何测试单参数模板类

下面就直接进入主题:如何对单参数模板类进行测试?

有以下模板类

//不用纠结于代码细节,只为说明

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*


在前面的例子中,被测试模板类只有1个类型参数,如果是多个类型参数呢,那该如何测试?


两个类型参数的模板类

//如果有两个类型参数

template <class E, class F>

class Que

{

public:

Que() {}

void Enque(const E& el) {}

E* Deque() {}

F size() const

{

return (F)123;

}

};


大家可以静静的想几分钟,看能不能解决这个问题吧~~


3、如何测试多参数模板类

下面就开始讨论这个主题:如何对多参数模板类进行测试?

不能照搬前面方案当被测试模板类有两个乃至多个类型参数时,再按前面例子的办法来进行就行不通了,由于gtest模板类测试宏仅接收1个模板参数,那该如何处理这个问题呢?


我的解决方案

将多个参数放在1个结构体里,做成1个模板类,将该模板类作为1个类型。


将多个参数组合成结构体 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;

};


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐