一个好的开发工具能够极大的提高工作效率,而好的开发工具是智慧与努力的结晶。
这里包括2个宏:CppUnitTest_CreateSuite和CppUnitTest_CreateMain
CppUnitTest_CreateMain用来产生单元测试主框架,产生的文件为alltest.cpp,如下:
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
int main(int argc, char** argv)
{
CppUnit::TextUi::TestRunner runner ;
// 从注册的TestSuite中获取特定的TestSuite, 没有参数获取未命名的TestSuite.
CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry("alltest") ;
// 添加这个TestSuite到TestRunner中
runner.addTest( registry.makeTest() ) ;
// 运行测试
runner.run() ;
}
CppUnitTest_CreateSuite宏用法:
1、定义一个类(头文件、源文件),并定义好基本的方法或函数(参数、返回值任意);
2、打开定义的源文件,执行此宏;
3、稍后,选择单元测试保存的路径;
4、手动修改、添加测试数据等。
局限:
1、此宏是针对源文件而写,如果在头文件中也可以,自己可以修改一下:使用前文讲的切换宏,首先从头文件切换到源文件即可,当前如果在头文件中执行,只产生了基本的结构,针对每个自定义函数需要自己写对应的测试函数。
2、对于重载函数并没有区分,需要再手动更改。
首先看一下宏运行后的效果:
定义的头文件:
#ifndef XXXXX_H
#define XXXXX_H
class CXXXXXX
{
public:
CXXXXXX();
~CXXXXXX();
void XXXXX1(int n);
void XXXXX1(double f) ;
int XXXXX2(void);
void* XXXXX3(int array[]);
};
#endif
定义的源文件:
#include "test.h"
CXXXXXX::CXXXXXX()
{
}
CXXXXXX::~CXXXXXX()
{
}
void CXXXXXX::XXXXX1(int n)
{
// .....
}
void CXXXXXX::XXXXX1(double f)
{
// .....
}
int CXXXXXX::XXXXX2(int n)
{
// .....
}
void CXXXXXX::XXXXX3(int array[])
{
// .....
}
宏执行后,产生的单元测试用例头文件和源文件为:
#ifndef _CXXXXXX_TEST_H_
#define _CXXXXXX_TEST_H_
#include "cppunit/extensions/HelperMacros.h"
class CXXXXXXTest: public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(CXXXXXXTest);
CPPUNIT_TEST(XXXXX1Test);
CPPUNIT_TEST(XXXXX1Test);
CPPUNIT_TEST(XXXXX2Test);
CPPUNIT_TEST(XXXXX3Test);
CPPUNIT_TEST_SUITE_END();
public:
CXXXXXXTest();
~CXXXXXXTest();
void setUp();
void tearDown();
void XXXXX1Test(void);
void XXXXX1Test(void);
void XXXXX2Test(void);
void XXXXX3Test(void);
private:
/*add internal unit test functions and variables here*/
};
#endif
#include "CXXXXXXTest.h"
#include "CXXXXXX.h"
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CXXXXXXTest, "alltest" );
void CXXXXXXTest::CXXXXXXTest()
{
/* 构造函数 */
}
void CXXXXXXTest::~CXXXXXXTest()
{
/* 析构函数 */
}
void CXXXXXXTest::setUp()
{
/* initiation */
}
void CXXXXXXTest::tearDown()
{
/* release resources */
}
void CXXXXXXTest::XXXXX1Test()
{
CXXXXXX obj ;
obj.XXXXX1() ;
}
void CXXXXXXTest::XXXXX1Test()
{
CXXXXXX obj ;
obj.XXXXX1() ;
}
void CXXXXXXTest::XXXXX2Test()
{
CXXXXXX obj ;
obj.XXXXX2() ;
}
void CXXXXXXTest::XXXXX3Test()
{
CXXXXXX obj ;
obj.XXXXX3() ;
}
宏代码:
/**
创建CPPUnit单元测试自动生成工具,通常情况下,类定义完成后,在CPP中执行此宏
作者: 王丰亮
时间: 2012.02.18
*/
macro CppUnitTest_CreateSuite()
{
hbuf = GetCurrentBuf()
isymMax = GetBufSymCount (hbuf)
isym = 0
while (isym < isymMax)
{
symbolname = GetBufSymName (hbuf, isym)
//Msg(symname)
symbol = GetSymbolLocation(symbolname)
if (symbol == nil)
{
//Msg (symbolname # " was not found")
}
else if(symbol.Type == "Class")
{
// 判断是否以"Test"结尾
strEnd = strmid (symbolname, strlen(symbolname)-strlen("Test"), strlen(symbolname))
if(toupper(strEnd) == toupper("Test"))
{
Msg(cat(cat("Detect the classname \"", symbolname), "\" end with \"Test\", maybe it's already a TestSuit, Continue anyway?"))
}
hTmpTestBuf = NewBuf("ClassInfo")
//Msg(symbolname)
AppendBufLine(hTmpTestBuf, symbolname) // 类名
// 匹配成员函数
//Msg(symbol.Symbol)
patternExp = cat(symbolname, "::.+(")
//SearchInBuf (hbuf, pattern, lnStart, ichStart, fMatchCase, fRegExp, fWholeWordsOnly)
sSel = SearchInBuf (hbuf, patternExp, 0, 0, False, True, False)
while(sSel != nil)
{
strFuncName = strmid(GetBufLine(hbuf, sSel.lnFirst), sSel.ichFirst+strlen(symbolname)+2, sSel.ichLim-1)
//Msg(strFunName)
if(strFuncName != symbolname) // 构造函数
{
if(strFuncName != cat("~", symbolname)) // 析构函数
{
AppendBufLine(hTmpTestBuf, strFuncName) // 普通函数
}
}
sSel = SearchInBuf (hbuf, patternExp, sSel.lnFirst+1, 0, False, True, False)
}
CreateCppUnitTestFiles(hTmpTestBuf)
CloseBuf(hTmpTestBuf)
}
isym = isym + 1
}
}
macro CreateCppUnitTestFiles(hTmpTestBuf)
{
if(hTmpTestBuf == hNil)
stop
curLine = 0
strClassNameOrig = GetBufLine(hTmpTestBuf, curLine)
strClassName = cat(strClassNameOrig, "Test")
hUnitTestHeaderBuf = NewBuf(cat(strClassName, ".h"))
hUnitTestSourceBuf = NewBuf(cat(strClassName, ".cpp"))
if(hUnitTestHeaderBuf == hNil)
stop
if(hUnitTestSourceBuf == hNil)
stop
// 头文件
AppendBufLine(hUnitTestHeaderBuf, cat(cat("#ifndef _", toupper(strClassNameOrig)), "_TEST_H_") )
AppendBufLine(hUnitTestHeaderBuf, cat(cat("#define _", toupper(strClassNameOrig)), "_TEST_H_") )
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, "#include \"cppunit/extensions/HelperMacros.h\"" )
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, cat(cat("class ", strClassName), ": public CppUnit::TestFixture")
AppendBufLine(hUnitTestHeaderBuf, "{")
//AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, cat(cat(" CPPUNIT_TEST_SUITE(", strClassName), ");") )
// 源文件
AppendBufLine(hUnitTestSourceBuf, cat(cat("#include \"", cat(strClassName, ".h")), "\"") )
AppendBufLine(hUnitTestSourceBuf, cat(cat("#include \"", cat(strClassNameOrig, ".h")), "\"") )
AppendBufLine(hUnitTestSourceBuf, "")
AppendBufLine(hUnitTestSourceBuf, cat(cat("CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(", strClassName), ", \"alltest\" );"))
AppendBufLine(hUnitTestSourceBuf, "")
AppendBufLine(hUnitTestSourceBuf, cat(cat(cat("", strClassName), "::"), cat(strClassName, "()"))
AppendBufLine(hUnitTestSourceBuf, "{")
AppendBufLine(hUnitTestSourceBuf, " /* 构造函数 */")
AppendBufLine(hUnitTestSourceBuf, "}")
AppendBufLine(hUnitTestSourceBuf, "")
AppendBufLine(hUnitTestSourceBuf, cat(cat(cat("", strClassName), "::~"), cat(strClassName, "()"))
AppendBufLine(hUnitTestSourceBuf, "{")
AppendBufLine(hUnitTestSourceBuf, " /* 析构函数 */")
AppendBufLine(hUnitTestSourceBuf, "}")
AppendBufLine(hUnitTestSourceBuf, "")
AppendBufLine(hUnitTestSourceBuf, cat(cat("void ", strClassName), "::setUp()"))
AppendBufLine(hUnitTestSourceBuf, "{")
AppendBufLine(hUnitTestSourceBuf, " /* initiation */")
AppendBufLine(hUnitTestSourceBuf, "}")
AppendBufLine(hUnitTestSourceBuf, "")
AppendBufLine(hUnitTestSourceBuf, cat(cat("void ", strClassName), "::tearDown()"))
AppendBufLine(hUnitTestSourceBuf, "{")
AppendBufLine(hUnitTestSourceBuf, " /* release resources */")
AppendBufLine(hUnitTestSourceBuf, "}")
AppendBufLine(hUnitTestSourceBuf, "")
curLine = 1
lines = GetBufLineCount(hTmpTestBuf)
while(curLine < lines)
{
strFuncNameOrig = GetBufLine(hTmpTestBuf, curLine)
strFuncName = cat(strFuncNameOrig, "Test")
// 头文件测试函数宏
AppendBufLine(hUnitTestHeaderBuf, cat(cat(" CPPUNIT_TEST(", strFuncName), ");") )
curLine = curLine + 1
}
AppendBufLine(hUnitTestHeaderBuf, " CPPUNIT_TEST_SUITE_END();" )
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, "public:")
AppendBufLine(hUnitTestHeaderBuf, cat(cat(" ", strClassName), "();"))
AppendBufLine(hUnitTestHeaderBuf, cat(cat(" ~", strClassName), "();"))
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, " void setUp();")
AppendBufLine(hUnitTestHeaderBuf, " void tearDown();")
AppendBufLine(hUnitTestHeaderBuf, "")
curLine = 1
//lines = GetBufLineCount(hTmpTestBuf)
while(curLine < lines)
{
strFuncNameOrig = GetBufLine(hTmpTestBuf, curLine)
strFuncName = cat(strFuncNameOrig, "Test")
// 头文件测试函数声明
AppendBufLine(hUnitTestHeaderBuf, cat(cat(" void ", strFuncName), "();") )
// 源文件测试函数定义
AppendBufLine(hUnitTestSourceBuf, cat(cat("void ", strClassName), cat("::", cat(strFuncName,"()"))))
AppendBufLine(hUnitTestSourceBuf, "{")
AppendBufLine(hUnitTestSourceBuf, cat(cat(" ", strClassNameOrig), " obj ;"))
AppendBufLine(hUnitTestSourceBuf, cat(cat(" obj.", strFuncNameOrig), "() ;"))
AppendBufLine(hUnitTestSourceBuf, "}")
AppendBufLine(hUnitTestSourceBuf, "")
curLine = curLine + 1
}
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, "private:")
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, " /*add internal unit test functions and variables here*/")
AppendBufLine(hUnitTestHeaderBuf, "")
AppendBufLine(hUnitTestHeaderBuf, "};")
AppendBufLine(hUnitTestHeaderBuf, "#endif")
SaveBuf(hUnitTestHeaderBuf)
SaveBuf(hUnitTestSourceBuf)
}
macro CppUnitTest_CreateMain()
{
hUnitTestMainBuf = NewBuf("alltest.cpp")
if(hUnitTestMainBuf == nil)
stop
// 单元测试main.cpp
AppendBufLine(hUnitTestMainBuf, "#include <cppunit/extensions/TestFactoryRegistry.h>" )
AppendBufLine(hUnitTestMainBuf, "#include <cppunit/ui/text/TestRunner.h>" )
AppendBufLine(hUnitTestMainBuf, "")
AppendBufLine(hUnitTestMainBuf, "int main(int argc, char** argv)" )
AppendBufLine(hUnitTestMainBuf, "{")
AppendBufLine(hUnitTestMainBuf, " CppUnit::TextUi::TestRunner runner ;" )
AppendBufLine(hUnitTestMainBuf, "")
AppendBufLine(hUnitTestMainBuf, " // 从注册的TestSuite中获取特定的TestSuite, 没有参数获取未命名的TestSuite.")
AppendBufLine(hUnitTestMainBuf, " CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry(\"alltest\") ;")
AppendBufLine(hUnitTestMainBuf, " // 添加这个TestSuite到TestRunner中")
AppendBufLine(hUnitTestMainBuf, " runner.addTest( registry.makeTest() ) ;")
AppendBufLine(hUnitTestMainBuf, "")
AppendBufLine(hUnitTestMainBuf, " // 运行测试")
AppendBufLine(hUnitTestMainBuf, " runner.run() ;")
AppendBufLine(hUnitTestMainBuf, "")
AppendBufLine(hUnitTestMainBuf, "}")
// AppendBufLine(hUnitTestMainBuf, "")
SaveBuf(hUnitTestMainBuf)
}