用C C ++测试代码

我不知道你们每次编写代码和不同级别的测试时如何测试代码:unit testing,集成测试,……

例如,对于刚刚编写的函数的unit testing,你是否编写了另一组main函数和Makefile来测试它? 或者您是否修改项目的主要function以测试function。 或者你只是在调试下运行你的项目,并停止调用函数的位置并修改其参数的值?

我相信必须有一些方便和常见的方式,大多数人都在使用,只有我不知道。

测试驱动开发(TDD)的方法是首先编写测试,看它默认失败(即新测试成功失败),然后编写函数以通过测试。

通过这种方式,测试不是事后的想法,而是您的开发方法的核心。

因为在实现操作对象之前可能正在开发函数(方法),所以大多数TDD框架还提供了生成“模拟”对象的工具,这些对象将在实际实现类之前返回预期结果。

我个人推荐Google Test和Google Mock 。

比较CppTest和CppUnit我会选择CppTest。 CppTest具有较少的隐藏框架,IMO更易于理解和实现。 我个人希望看到主要切入点。 我还包括了Boost Unit Testing Framework。 它不是基于xUnit的。 我不是粉丝,但如果您已经在使用Boost库,那么合并将会很棒。


CppTest与CppUnit

易于创建unit testing和测试套件 。 CppUnit和CppTest都创建了类方法的unit testing,类本身派生自一些工具提供的Test类。 但是,CppTest的语法稍微简单一些,测试注册发生在类构造函数中。 在CppUnit的情况下,需要额外的宏CPPUNIT_TEST_SUITE和CPPUNIT_TEST_SUITE_ENDS。

运行测试 。 CppTest只是在测试套件上调用run方法,而CppUnit使用一个单独的TestRunner类,调用其run方法来运行测试。

扩展测试层次结构 。 在CppTest的情况下,始终可以通过创建从旧的inheritance的新类来扩展先前的测试套件。 新类将定义一些添加到unit testing池的附加function。 您只需在新类类型的对象上调用run方法。 相反,CppUnit要求您使用宏CPPUNIT_TEST_SUB_SUITE以及类inheritance来实现相同的效果。

生成格式化输出 。 CppTest和CppUnit都能够自定义输出。 但是,尽管CppTest有一个有用的预定义HTML输出格式化程序,但CppUnit却没有。 但是,CppUnit专门支持XML格式化。 两者都支持文本和编译器样式格式。

创建测试夹具 。 要使用测试夹具,CppUnit要求测试类派生自CppUnit :: TestFixture。 您必须提供设置和拆卸例程的定义。 对于CppTest,您需要仅为设置和拆除例程提供定义。 这绝对是一个更好的解决方案,因为它使客户端代码保持简单。 •预定义的实用程序宏支持。 CppTest和CppUnit都有一组可比较的断言宏,处理浮点数等等。

头文件 。 CppTest要求您包含单个头文件,而CppUnit客户端代码必须包含多个头,如HelperMacros.h和TextTestRunner.h,具体取决于所使用的function。

http://www.ibm.com/developerworks/aix/library/au-ctools3_ccptest/index.html?ca=drs-


CPPTEST

#include “cppTest.h” class myTestWithFixtures : public Test::Suite { void function1_to_test_some_code( ); void function2_to_test_some_code( ); public: myTestWithFixtures ( ) { TEST_ADD (function1_to_test_some_code) {...}; TEST_ADD (function2_to_test_some_code) {...}; } protected: virtual void setup( ) { ... }; virtual void tear_down( ) { ... }; }; int main ( ) { myTestWithFixtures tests; Test::TextOutput output(Test::TextOutput::Verbose); return tests.run(output); } 

http://www.ibm.com/developerworks/aix/library/au-ctools3_ccptest/index.html?ca=drs-


CppUnit的

 #include  #include  #include  class mystringTest : public CppUnit::TestFixture { public: void setUp() { ... }; void tearDown() { ... }; void function1_to_test_some_code() { ... }; void function2_to_test_some_code() { ... }; CPPUNIT_TEST_SUITE( mystringTest ); CPPUNIT_TEST( function1_to_test_some_code ); CPPUNIT_TEST( function2_to_test_some_code ); CPPUNIT_TEST_SUITE_END(); }; CPPUNIT_TEST_SUITE_REGISTRATION( mystringTest ); 

没有宏

 int main () { CppUnit::TestSuite* suite = new CppUnit::TestSuite("mystringTest"); suite->addTest(new CppUnit::TestCaller("checkLength", &mystringTest::checkLength)); suite->addTest(new CppUnit::TestCaller("checkValue", &mystringTest::checkLength)); // client code follows next CppUnit::TextTestRunner runner; runner.addTest(suite); runner.run(); return 0; } 

http://www.ibm.com/developerworks/aix/library/au-ctools2_cppunit/


增强unit testing框架

 #include  using namespace std; struct CMyFooTestFixture { CMyFooTestFixture() { ... } //SetUp ~CMyFooTestFixture() { ... } //TearDown void function1_to_test_some_code(CMyFoo& foo) { ... }; void function2_to_test_some_code(CMyFoo& foo) { ... }; } BOOST_FIXTURE_TEST_SUITE(MyFooTest, CMyFooTestFixture); BOOST_AUTO_TEST_CASE(function1_to_test_some_code) { CMyFoo foo; function1_to_test_some_code(foo); } BOOST_AUTO_TEST_CASE(function1_to_test_some_code2) { CMyFoo foo; function1_to_test_some_code(foo); } BOOST_AUTO_TEST_SUITE_END(); 

http://www.beroux.com/english/articles/boost_unit_testing/

我用googletest / gtest

我学会了喜欢googletest / googlemock。 它们是一个非常强大的组合,易于使用。 他们的维基页面上还有很多文档可用。

googletest:code.google.com/p/googletest/wiki/GoogleTestPrimer

googlemock:code.google.com/p/googlemock/wiki/ForDummies

我通常这样做:

 int foo(int bar) { ... } #ifdef FOO_UNITTEST int main(int argc, char *argv[]) { // tests } #endif 

我有一个在CFLAGS中有-DFOO_UNITTEST的makefile。

它很笨拙,但你总是在你的代码旁边进行测试。

我喜欢googletest和googlemock 。 非常容易配置和记录良好, 这里有一个很好的框架介绍。

你看过http://CppUnit.sourceforge.net吗?

您还应该考虑运行一个测试覆盖率工具,以查看您的测试是否真正运用了足够的代码来进行一组测试。 请参阅C的SD测试覆盖率 。

我喜欢UnitTest ++ 。 设置起来非常简单,编写测试比使用典型的CppUnit更容易。 每个测试都有很少的编码开销,所以你更有可能编写它们!

至于我测试的内容,我倾向于测试类的公共接口,但如果我只是做一些重构并将事情分解成更小的函数,我就不会为每个函数编写一组测试 – 它们应该是由测试公共接口的测试覆盖。 只要公共界面按照测试工作,一切都在世界上很好。

我用boost.test 。 我从cppunit转移到它,这很好,但是像java一样,这是一个问题,因为junit使用reflection来查找并运行测试,因为这在c ++中不可用,你必须使用宏来注册你的测试,在cppunit你必须在三个不同的地方声明,注册和定义您的测试。 boost.test允许您在一个语句中声明,注册和定义测试,这非常好。

我的一般方法是TDD新代码,并尝试明智地使用unit testing遗留代码。 我esp测试在不同平台上不同的任何代码,以确保它们的行为相同并继续表现相同。

我构建我的项目,以便每个库或可执行项目也有一个unit testing项目。 对于可执行测试,我在测试项目中包含可执行源文件(main除外),并将我的测试添加到新文件中。 对于库测试,我通常只是链接到库,除非我测试dll的私有部分然后我使用可执行方法。

使用CMake可以抽象源项目和测试项目之间的任何重复。 此外, CTest可以与任何可执行文件中的测试打包的unit testing框架很好地集成。 这使您可以一次性在解决方案中运行所有测试可执行文件,并报告结果摘要。 它还集成了一个名为CDash的持续集成框架。

有关TDD的说明,很多人将其视为测试驱动开发,但它可以是测试驱动设计。 这是一个非常好的方式,专注于敏捷设计,使用TDD设计我的软件以及写它真的打开了我的眼睛。

我通常从与MinUnit一样复杂的东西开始,然后构建一组适合我正在努力适应该项目惯例的项目的宏。

每个组件都有一个可执行文件,用于构建和运行该组件的unit testing。

我不使用调试器,因为这需要人工干预,因此您不能将其用于自动回归。 我不修改主可执行文件,因为它通常涉及许多组件,并且非常复杂,没有很多宏来打开和关闭位。 使用make创建新目标非常简单。