CppUnit使用指南

 

测试驱动开发的原则:

Ø        先写测试代码,然后编写符合测试的代码。至少做到完成部分代码后,完成对应的测试代码;

 

Ø        测试代码不需要覆盖所有的细节,但应该对所有主要的功能和可能出错的地方有相应的测试用例;

 

Ø        发现 bug,首先编写对应的测试用例,然后进行调试;

 

Ø        不断总结出现 bug 的原因,对其他代码编写相应测试用例;

 

Ø        每次编写完成代码,运行所有以前的测试用例,验证对以前代码影响,把这种影响尽早消除;

 

Ø        不断维护测试代码,保证代码变动后通过所有测试;

 

Ø        在编码前:他可以强迫你对需求进行详细的分析。

 

Ø        在编码时:他可以使你对over coding保持警觉。

 

Ø        在重构时:可以确保新的设计能够兼容旧版本的功能。

 

Ø        在团队开发时:可以确保自己的单元是无误的。

 

 

CppUnit的原理

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,这样测试用例之间就没有交叉影响。

 

撰写TestCase必须注意以下几点:

 

Ø         可以自动执行,不用人手操作。

 

Ø         自动返回测试结果。

 

Ø         绝对的独立,不能与其他TestCase有任何联系。就算测试同一个函数的不同功能也需要分开。每个TestCase可以说是一个孤岛。

 

 

 

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

 

class MathTest : public CppUnit::TestFixture {

 

protected:

 

       int m_value1, m_value2;

 

      

 

public:

 

       MathTest() {}

 

      

 

       // 初始化函数

 

       void setUp () {

 

              m_value1 = 2;

 

              m_value2 = 3;

 

       }

 

       // 测试加法的测试函数

 

       void testAdd () {

 

              // 步骤(2), fixture 进行操作

 

              int result = m_value1 + m_value2;

 

              // 步骤(3),验证结果是否争取

 

              CPPUNIT_ASSERT( result == 5 );

 

       }

 

       // 没有什么清理工作没有定义 tearDown.

 

}

 

 

在测试函数中对执行结果的验证成功或者失败直接反应这个测试用例的成功和失败。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)      // expectedactual之间差大于delta时失败

 

 

要把对 fixture 的一个测试函数转变成一个测试用例,需要生成一个 CppUnit::TestCaller 对象。而最终运行整个应用程序的测试代码的时候,可能需要同时运行对一个 fixture 的多个测试函数,甚至多个 fixture 的测试用例。CppUnit 中把这种同时运行的测试案例的集合称为 TestSuite。而 TestRunner 则运行测试用例或者 TestSuite,具体管理所有测试用例的生命周期。目前提供了 3 TestRunner,包括:

 

Ø         CppUnit::TextUi::TestRunner        // 文本方式的TestRunner

 

Ø         CppUnit::QtUi::TestRunner            // QT方式的TestRunner

 

Ø         CppUnit::MfcUi::TestRunner         // MFC方式的TestRunner

 

下面是一个TestRunner的例子:

 

CppUnit::TextUi::TestRunner runner;

 

  CppUnit::TestSuite *suite= new CppUnit::TestSuite();

 

 

 

  // 添加一个测试用例

 

  suite->addTest(new CppUnit::TestCaller<MathTest> (

 

         "testAdd", testAdd));

 

 

 

  // 指定运行TestSuite

 

  runner.addTest( suite );

 

  // 开始运行, 自动显示测试进度和测试结果

 

发布了87 篇原创文章 · 获赞 2 · 访问量 18万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章