您的位置:首页 > 编程语言 > C语言/C++

利用cppunit框架进行单元测试的例子,结合gcov,lcov实现对测试覆盖情况的统计

2012-06-11 23:21 260 查看
下面是一个利用cppunit框架进行单元测试的例子,结合gcov,lcov实现对
测试覆盖情况的统计

测试部分 由两部分组成:testfixture, main ;用两种颜色分开以示区别。

原理:

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

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

对 fixture 进行初始化,及其他初始化操作,比如:生成一组被测试的对象,初始化值;
按照要测试的某个功能或者某个流程对 fixture 进行操作;
验证结果是否正确;
对 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就可以查看了,可通过点击左边的目录文件查看具体的覆盖情况,对于未覆盖的语句、分支或流程,可继续设计用例,以提高覆盖。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐