cppunit测试的一个小例子

下面是一个利用cppunit框架进行单元测试的例子,结合gcov,lcov实现对    测试覆盖情况的统计
测试部分 由两部分组成:testfixture, main ;用两种颜色分开以示区别。
原理:

在 CppUnit 中,一个或一组测试用例的测试对象被称为 Fixture(设施,下文为方便理解尽量使用英文名称)。Fixture 就是被测试的目标,可能是一个对象或者一组相关的对象,甚至一个函数。

有了被测试的 fixture,就可以对这个 fixture 的某个功能、某个可能出错的流程编写测试代码,这样对某个方面完整的测试被称为TestCase(测试用例)。通常写一个 TestCase 的步骤包括:

  1. 对 fixture 进行初始化,及其他初始化操作,比如:生成一组被测试的对象,初始化值;
  2. 按照要测试的某个功能或者某个流程对 fixture 进行操作;
  3. 验证结果是否正确;
  4. 对 fixture 的及其他的资源释放等清理工作。

对 fixture 的多个测试用例,通常(1)(4)部分代码都是相似的,CppUnit 在很多地方引入了 setUp 和 tearDown 虚函数。可以在 setUp 函数里完成(1)初始化代码,而在 tearDown 函数中完成(4)代码。具体测试用例函数中只需要完成(2)(3)部分代码即可,运行时 CppUnit 会自动为每个测试用例函数运行 setUp,之后运行 tearDown,这样测试用例之间就没有交叉影响。

对 fixture 的所有测试用例可以被封装在一个 CppUnit::TestFixture 的子类(命名惯例是[ClassName]Test)中。然后定义这个fixture 的 setUp 和 tearDown 函数,为每个测试用例定义一个测试函数(命名惯例是 testXXX)。下面是个简单的例子:


#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>

// 定义测试类
class StringTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(StringTest); // 定义测试包
CPPUNIT_TEST(testSwap); // 添加测试用例1
CPPUNIT_TEST(testFind); // 添加测试用例2
CPPUNIT_TEST_SUITE_END(); // 结束测试包定义

public:
void setUp() // 初始化
{
m_str1 = "Hello, world";
m_str2 = "Hi, cppunit";
}

void tearDown() // 清理
{
}

void testSwap() // 测试方法1
{
std::string str1 = m_str1;
std::string str2 = m_str2;
m_str1.swap(m_str2);

CPPUNIT_ASSERT(m_str1 == str2);
CPPUNIT_ASSERT(m_str2 == str1);
}
void testFind() // 测试方法2
{
int pos1 = m_str1.find(',');
int pos2 = m_str2.rfind(',');

CPPUNIT_ASSERT_EQUAL(5, pos1);
CPPUNIT_ASSERT_EQUAL(2, pos2);
}

protected:
std::string m_str1;
std::string m_str2;
};

CPPUNIT_TEST_SUITE_REGISTRATION(StringTest); // 自动注册测试包


int main(int argc, char* argv[])
{
CppUnit::TestResult r; 
CppUnit::TestResultCollector rc;
r.addListener(&rc); // 准备好结果收集器 

CppUnit::TestRunner runner; // 定义执行实体
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
runner.run(r); // 运行测试

CppUnit::TextOutputter o(&rc, std::cout);
o.write(); // 将结果输出

return rc.wasSuccessful() ? 0 : -1;
}


在测试函数中对执行结果的验证成功或者失败直接反应这个测试用例的成功和失败。CppUnit 提供了多种验证成功失败的方式:

CPPUNIT_ASSERT(condition)   // 确信condition为真 CPPUNIT_ASSERT_MESSAGE(message, condition)   // 当condition为假时失败, 并打印message CPPUNIT_FAIL(message)             // 当前测试失败, 并打印message CPPUNIT_ASSERT_EQUAL(expected, actual)     // 确信两者相等 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual)   // 失败的同时打印message CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta)   // 当expected和actual之间差大于delta时失败   
---------------------------------------------------------------------------------------------------------------
root@OptiPlex-330:/opt/src#ls
stringtest.cpp

gcov是一个可用于C/C++的代码覆盖工具,是gcc的内建工具。下面介绍一下如何利用gcov来收集代码覆盖信息。
想要用gcov收集代码覆盖信息,需要在gcc编译代码的时候加上这2个选项 “-fprofile-arcs -ftest-coverage”,把这个简单的程序编译一下

1)
root@zyf-OptiPlex-330:/opt/src# g++ stringtest.cpp -fprofile-arcs -ftest-coverage -lcppunit -ldl -o stringtest
root@zyf-OptiPlex-330:/opt/src# ls
stringtest  stringtest.cpp  stringtest.gcno


2)
root@OptiPlex-330:/opt/src# ./stringtest
OK (2 tests)
root@OptiPlex-330:/opt/src# ls
stringtest  stringtest.cpp  stringtest.gcda  stringtest.gcno



3)

root@OptiPlex-330:/opt/src# lcov -d . -t 'stringtest' -o 'string_test.info' -b . -c
Capturing coverage data from .
Found gcov version: 4.5.2
Scanning . for .gcda files ...
Found 1 data files in .
Processing stringtest.gcda
Finished .info-file creation
root@OptiPlex-330:/opt/src# ls
stringtest  stringtest.cpp  stringtest.gcda  stringtest.gcno  string_test.info

4)
root@OptiPlex-330:/opt/src# genhtml -o result string_test.info 
Reading data file string_test.info
Found 37 entries.
Found common filename prefix "/usr/include/c++/4.5"
Writing .css and .png files.
Generating output.
Processing file /opt/src/stringtest.cpp
Processing file ostream
Processing file sstream
Processing file streambuf
Processing file iostream
Processing file iosfwd
Processing file new
Processing file backward/auto_ptr.h
Processing file bits/stl_iterator_base_funcs.h
Processing file bits/stl_uninitialized.h
Processing file bits/deque.tcc
Processing file bits/stl_construct.h
Processing file bits/stl_iterator.h
Processing file bits/char_traits.h
Processing file bits/basic_ios.h
Processing file bits/ios_base.h
Processing file bits/allocator.h
Processing file bits/stl_vector.h
Processing file bits/stl_pair.h
Processing file bits/stl_deque.h
Processing file bits/basic_string.h
Processing file bits/basic_string.tcc
Processing file bits/stl_iterator_base_types.h
Processing file ext/type_traits.h
Processing file ext/atomicity.h
Processing file ext/new_allocator.h
Processing file x86_64-linux-gnu/bits/gthr-default.h
Processing file /usr/local/include/cppunit/Message.h
Processing file /usr/local/include/cppunit/TestAssert.h
Processing file /usr/local/include/cppunit/AdditionalMessage.h
Processing file /usr/local/include/cppunit/TestFixture.h
Processing file /usr/local/include/cppunit/TestCaller.h
Processing file /usr/local/include/cppunit/extensions/TestFactory.h
Processing file /usr/local/include/cppunit/extensions/AutoRegisterSuite.h
Processing file /usr/local/include/cppunit/extensions/TestFixtureFactory.h
Processing file /usr/local/include/cppunit/extensions/TestSuiteFactory.h
Processing file /usr/local/include/cppunit/extensions/TestSuiteBuilderContext.h
Writing directory view page.
Overall coverage rate:
  lines......: 52.6% (195 of 371 lines)
  functions..: 50.6% (90 of 178 functions)
  branches...: 32.9% (135 of 410 branches)
root@OptiPlex-330:/opt/src# ls
result  stringtest  stringtest.cpp  stringtest.gcda  stringtest.gcno  string_test.info

打开result文件夹下的index.html就可以查看了,可通过点击左边的目录文件查看具体的覆盖情况,对于未覆盖的语句、分支或流程,可继续设计用例,以提高覆盖。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值