前言
C++集成的unit test框架常用的是boost和CppTest,更多的是在测试语法对否。而我需要的单元测试是针对功能而言,旨在检测该函数的计算结果是否正确。为了方便添加并维护后续的unit test,自己实现了一个简易的unit test框架。该框架主要有基类、派生类和suite类。基类是实现所有unit test 的共有操作,比如compare、print、readData之类的操作;派生类则实现每个unit test的独有操作run函数(为了方便suite类,该操作必须声明成run函数);suite类相当于是一个容器类,将派生类中的每个类都实例化后,并执行run操作,达到测试结果输出的目的。下面在说明自己的test 框架前,先用一个简单例子说明一下该框架如何实现有效。
1、基类(需要在派生类中覆盖的函数必须声明成virtual虚函数)
2、派生类(重载基类的虚函数)
3、Suite类(vector容器,实例化每一个派生类,使其执行派生类重载的函数,而不是基类的虚函数)
先来看一个关于访问不到派生类自己的重载函数的错误实例:
#include <iostream>
using namespace std;
class A
{
public:
virtual void print() //关键字virtual声明一个函数是虚函数
{
cout<<"我是类A"<<endl;
}
};
class B : public A
{
public:
void print()
{
cout<<"我是类B"<<endl;
}
};
int main(int argc, char* argv[])
{
vector<A> aa;
A *p = new B();
aa.push_back(*p);
A *q = new B();
aa.push_back(*q);
A *w = new B();
aa.push_back(*w);
cout<<aa.size()<<endl;
for(vector<A>::iterator it = aa.begin();it != aa.end();it++)
{
it->print();
}
return 0;
}
该运行结果是,print()函数调用的都是基类的print,【我是类A】,并不是我们的本意。vector容器中应是基类型的指针方可!
正确的例子:定义是指针类型的vector
#include <iostream>
using namespace std;
class A
{
public:
virtual void print() //关键字virtual声明一个函数是虚函数
{
cout<<"我是类A"<<endl;
}
};
class B : public A
{
public:
virtual void print()
{
cout<<"我是类B"<<endl;
}
};
int main(int argc, char* argv[])
{
vector<A*> aa;
A *p = new B();
aa.push_back(p);
A *q = new B();
aa.push_back(q);
A *w = new B();
aa.push_back(w);
cout<<aa.size()<<endl;
for(unsigned int i = 0; i < aa.size();i++)
{
aa[i]->print();
}
return 0;
}
此时运行结果如下:【我是类B】【我是类B】【我是类B】
note: vector容器是指针类型时,push进去的应该是地址,而不是内容。
综合Suite类,该简易的unit test框架可以简单实现以下:
#include <vector>
#include <iostream>
using namespace std;
class A
{
public:
virtual void print() //关键字virtual声明一个函数是虚函数
{
cout<<"我是类A"<<endl;
}
};
class B : public A
{
public:
virtual void print()
{
cout<<"我是类B"<<endl;
}
};
class C : public A
{
public:
virtual void print()
{
cout<<"我是类C"<<endl;
}
};
class Suite {
public:
void run();
vector<A*> VA;
};
void Suite::run()
{
A *p = new B();
VA.push_back(p);
A *q = new C();
VA.push_back(q);
for(unsigned int i = 0; i < VA.size();i++)
{
VA[i]->print();
}
}
int main(int argc, char* argv[])
{
Suite suite;
suite.run();
return 0;
}
4、自己写的一个工程例子(待完善)
class Suite {
public:
Suite(){};
~Suite()
{
std::vector<unitTest<u8>*>().swap(UTu8);
std::vector<unitTest<u16>*>().swap(UTu16);
};
void run();
public:
std::vector<unitTest<u8>*> UTu8;
std::vector<unitTest<u16>*> UTu16;
};
void Suite::run()
{
//for u8 cases:
unitTest<u8> *t1 = new testu8CCAnalyzer(true,"(LayerID_0)_NIR_248-86.tif",true,true);
UTu8.push_back(t1);
unitTest<u8> *t2 = new testU8GenImgMetricClass(true,".\\testdataset\\(LayerID_200)_IR_52.tif", 0.51560330);
UTu8.push_back(t2);
//for u16 cases:
unitTest<u16> *t3 = new testu16CCAnalyzer(true,"(LayerID_0)_NIR_248-86.tif",true,true);
UTu16.push_back(t3);
unitTest<u16> *t4 = new testU16GenImgMetricClass(true, "testdataset\\burst_875_frame_0_width_384_height_384_depth_12_2.tif", 0.00000000);
UTu16.push_back(t4);
for(unsigned int i = 0; i < UTu8.size();i++)
{
UTu8[i]->run();
}
for(unsigned int i = 0; i < UTu16.size();i++)
{
UTu16[i]->run();
}
}
关于自己写的这个suite类和singleton有什么关系还待探索