本文主要是论述CppUnit在C++项目中的应用,如何使用该单元测试,以及如何生成和查看测试报告和覆盖率报告。
1.CppUnit 的安装。
本文以在Ubuntu下开发C++项目为例。
首先,读者需要选好速度较好的源去download一些应用程序,本文主要使用到gcc,cppunit,所以读者可以使用下面的命令去安装,使用
sudo -i切换到root账户。
使用apt-cache search gcc 和apt-cache search cppunit去查看当前源中是否存在gcc,cppunit的应用程序。然后使用apt-get install gcc,cppunit去安装。如果依赖其他应用或者程序包,请相应下载。
2.简单应用的设计。
设计一个简单的计算器的类,能够进行加减乘除运算。头文件 Calculator.h 如下:
#include <string>
#include <stdexcept>
#include <cppunit/portability/Stream.h>
#ifndef CALCULATOR_H_
#define CALCULATOR_H_
class DivideByZeroException : public std::runtime_error
{
public:
DivideByZeroException() : std::runtime_error( "Divide By Zero Exception" )
{
}
};
class Calculator {
public:
Calculator();
virtual ~Calculator();
const double add(const double &a, const double &b) ;
const double subtract(const double &a, const double &b);
const double multiply(const double &a,const double &b);
const double divide(const double &a,const double &b);
};
#endif /* CALCULATOR_H_ */
实现该类 Calculator.cpp。
#include "Calculator.h"
Calculator::Calculator() {
}
Calculator::~Calculator() {
}
const double Calculator::add(const double &a, const double &b) {
return a + b;
}
const double Calculator::subtract(const double &a, const double &b) {
return a - b;
}
const double Calculator::multiply(const double &a, const double &b) {
return a * b;
}
const double Calculator::divide(const double &a, const double &b) {
if(b <=0.000001)
{
throw DivideByZeroException();
}
return a / b;
}
接下来是书写测试代码,CalculatorTest.h
#ifndef CALCULATORTEST_H
#define CALCULATORTEST_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestFixture.h>
/*#include "MyTest.h"*/
#include "Calculator.h"
/*class CalculatorTest : public MyTest*/
class CalculatorTest : public CPPUNIT_NS::TestCase
{
/*CPPUNIT_TEST_SUB_SUITE( CalculatorTest, MyTest);*/
CPPUNIT_TEST_SUITE( CalculatorTest );
CPPUNIT_TEST( testAdd );
CPPUNIT_TEST( testSubtract );
CPPUNIT_TEST( testMultiply );
CPPUNIT_TEST( testDivide);
CPPUNIT_TEST_EXCEPTION( testDivideByZero, DivideByZeroException );
CPPUNIT_TEST_SUITE_END();
public:
/* Initial something here, e.g, instance the Calculator.*/
void setUp();
/* destory something here, e.g, destory the Calculator instance.*/
void tearDown();
/* test method to test add function.*/
void testAdd();
/* test method to test subtract function.*/
void testSubtract();
/* test method to test multiply function.*/
void testMultiply();
/* test method to test divide function,but the divisor is not zero.*/
void testDivide();
/* test method to test divide function,but the divisor is zero.*/
void testDivideByZero();
private:
Calculator *calculator;
};
#endif
之后是测试代码的实现,CalculatorTest.cpp
#include <cppunit/config/SourcePrefix.h>
#include "Calculator.h"
#include "CalculatorTest.h"
CPPUNIT_TEST_SUITE_REGISTRATION( CalculatorTest );
void
CalculatorTest::setUp()
{
std::cout<<"\nSetup()";
calculator = new Calculator;
}
void
CalculatorTest::tearDown()
{
std::cout<<"->tearDown()\n";
delete calculator;
}
void
CalculatorTest::testAdd()
{
double a = 2.0;
double b = 3.0;
const double result = calculator->add(a,b);
CPPUNIT_ASSERT_DOUBLES_EQUAL( 5.0, result, 0.1 );
}
void
CalculatorTest::testSubtract()
{
double a = 5.0;
double b = 3.0;
const double result = calculator->subtract(a,b);
CPPUNIT_ASSERT_DOUBLES_EQUAL( 2.0, result, 0.1 );
}
void
CalculatorTest::testMultiply()
{
double a = 5.0;
double b = 3.0;
const double result = calculator->multiply(a,b);
CPPUNIT_ASSERT_DOUBLES_EQUAL( 15.0, result, 0.1 );
}
void
CalculatorTest::testDivide()
{
double a = 5.0;
double b = 3.0;
const double result = calculator->divide(a,b);
CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.667, result, 0.1 );
}
void
CalculatorTest::testDivideByZero()
{
double a = 5.0;
double b = 0.0;
try
{
const double result = calculator->divide(a,b);
}
catch(DivideByZeroException e)
{
throw;
}
}
程序入口代码 Main.cpp
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
int
main( int argc, char* argv[] )
{
// Create the event manager and test controller
CPPUNIT_NS::TestResult controller;
// Add a listener that colllects test result
CPPUNIT_NS::TestResultCollector result;
controller.addListener( &result );
// Add a listener that print dots as test run.
CPPUNIT_NS::BriefTestProgressListener progress;
controller.addListener( &progress );
// Add the top suite to the test runner
CPPUNIT_NS::TestRunner runner;
runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
runner.run( controller );
// Print test in a compiler compatible format.
CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() );
outputter.write();
return result.wasSuccessful() ? 0 : 1;
}
简单的Makefile代码:Makefile
#SRC=Main.cpp ./Calculator.cpp ./CalculatorTest.cpp
SRC=Main.cpp ./Calculator.cpp ./CalculatorTest.cpp
CXX=g++
CC=gcc
CXXFLAGS=-I./
libflag = -L/usr/local/lib
LDFLAGS=-lcppunit -lrt -lcurses -ldl
TESTFLAG = -ftest-coverage -fprofile-arcs
All:main
main: $(SRC)
$(CXX) -g -o $@ $(CXXFLAGS) ${libflag} $(LDFLAGS) $(SRC) -pg ${TESTFLAG}
clean:
rm -f *.o main
运行make命令,生成可执行和程序main,
使用下列命令执行程序
./main
结果如下:
CalculatorTest::testAdd
Setup()->tearDown()
: OK
CalculatorTest::testSubtract
Setup()->tearDown()
: OK
CalculatorTest::testMultiply
Setup()->tearDown()
: OK
CalculatorTest::testDivide
Setup()->tearDown()
: OK
CalculatorTest::testDivideByZero
Setup()->tearDown()
: OK
OK (5)
我会继续完善,有些地方还不好的