C++单元测试框架比较

335

我知道已经有一些关于推荐C++单元测试框架的问题,但是所有答案都没有帮助,因为它们只推荐了其中一个框架,而没有提供任何有关(功能)比较的信息。

我认为最有趣的框架是CppUnit、Boost和新的Google测试框架。有人已经做过比较了吗?


我有自己的基于IOC的测试框架,我更喜欢它,因为它不仅仅是其他所有测试框架的克隆,而且解决了我发现其他测试框架存在的所有问题。您可以通过从类派生来编写测试用例,而不是使用宏。宏仅用于断言,因为它们提供反射。测试统计信息的定制输出。从IOC脚本运行,因此您可以选择测试什么,多久以及使用什么参数进行测试。 - CashCow
从开发的角度来看,这是非常出色的,因为当我添加自己的测试时,我可以在不同时运行其他人的测试的情况下运行它。因此,我知道我的代码是否工作。 - CashCow
9个回答

132

有一个新的播放器是Google Test(也称为Google C++测试框架),虽然它很不错。

#include <gtest/gtest.h>

TEST(MyTestSuitName, MyTestCaseName) {
    int actual = 1;
    EXPECT_GT(actual, 0);
    EXPECT_EQ(1, actual) << "Should be equal to one";
}

主要功能:

  • 可移植
  • 致命和非致命断言
  • 易于使用的断言信息:ASSERT_EQ(5, Foo(i)) << " where i = " << i;
  • Google Test 自动检测您的测试,不需要枚举它们以便运行
  • 使扩展您的断言词汇变得容易
  • 死亡测试(见高级指南)
  • SCOPED_TRACE用于子程序循环
  • 您可以决定运行哪些测试
  • XML测试报告生成
  • 夹具/模拟/模板...

3
我非常喜欢使用Google Test相比其他测试框架,特别是其中包含的模拟能力,可以在Google Mock框架中找到。 - Mike
8
我在我的新测试框架CATCH中提供了所有这些功能(尽管有些还没有公开),还有更多。查看我的回答获取链接。 - philsquared
2
将其与Google C++ Mocking框架结合使用,使其成为C++代码单元测试的强大xUnit测试框架。 - ratkok
5
在构建过程中运行与测试检测是两回事。构建过程中的运行取决于您的构建系统。测试检测意味着您不必在另一个类中列出所有测试,只需创建测试方法即可。 - Wernight
1
我不喜欢他们过度使用宏,而且使用像TEST这样的常见单词可能会与其他东西冲突。GTEST会更好一些,不太可能发生冲突。 - CashCow
显示剩余5条评论

129

我刚刚发布了自己的框架Catch2。它仍在开发中,但我相信它已经超越了大多数其他框架。

  • 只需头文件即可使用
  • 基于函数和方法的测试自动注册
  • 将标准C++表达式分解为左值和右值(因此您不需要一整套断言宏)。
  • 支持基于函数的夹具中的嵌套部分
  • 使用自然语言命名测试 - 自动生成函数/方法名称

它还具有Objective-C绑定。该项目托管在Github上。


3
doctest 是我对 Catch 进行重新实现的,重点关注编译速度 - 查看FAQ 以了解它们的区别。 - onqtam
3
我在比较所有测试框架时真的很困惑(其中之一现在我必须选择)。您能否写下您自己的答案,比较和对比doctest与Catch以及其他提供的框架? - einpoklum
@einpoklum 如果我能的话,我会的 - 但问题被关闭为“不具建设性”,我只能写评论... - onqtam
你应该添加:在失败时不要继续执行,这意味着测试将立即停止。Google Test自豪地宣称没有异常,但如果您不检查返回代码(至少这是默认行为),则会在失败时继续执行,这意味着如果您不这样做,测试将继续进行。我觉得这很可笑。 - ceztko

108

1
正如我所写的:所有答案都只推荐一个框架,但没有将该框架与另一个进行比较。 - housemaister
8
批评意见:这篇文章虽然不错,但是它的出处是2004年,没有包括Google Test。Translated: One criticism: the article, while good, is from 2004 and doesn't include Google Test. - richq
2
在第一个链接中,你会看到两个比较。除了谷歌的新框架之外,大部分信息仍然相关。(而且CppUnit并不是最有趣的,使用起来太笨拙了) - Luc Hermitte
1
已修复链接并扩充了答案,包含更近期的比较。 - Sam Saffron
第二个链接已经失效了。请问你能否修复一下? - Yuchen
显示剩余3条评论

55

Boost测试库是一个非常好的选择,特别是如果你已经在使用Boost。

// TODO: Include your class to test here.
#define BOOST_TEST_MODULE MyTest
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(MyTestCase)
{
    // To simplify this example test, let's suppose we'll test 'float'.
    // Some test are stupid, but all should pass.
    float x = 9.5f;

    BOOST_CHECK(x != 0.0f);
    BOOST_CHECK_EQUAL((int)x, 9);
    BOOST_CHECK_CLOSE(x, 9.5f, 0.0001f); // Checks differ no more then 0.0001%
}

它支持:

  • 自动或手动测试注册
  • 许多断言
  • 集合的自动比较
  • 各种输出格式(包括XML
  • 固定装置/ 模板

PS:我写了一篇关于它的文章,可能会帮助你入门:C++ Unit Testing Framework: A Boost Test Tutorial


我曾经使用过 Boost test,并且很喜欢它,除了它似乎在每次发布之间都有重大变化。这已经足够困难了,要向我的客户推荐单元测试,而不必花费更多时间(和他们的资金)来修复 API 更改后的测试,而不是修复应该进行测试的代码。最终,我放弃了它并编写了自己的测试框架 - 这大约是5年前。 - Component 10

27

16

我最近发布了xUnit++,这是作为Google Test和Boost Test Library的替代品(查看比较)而发布的。如果您熟悉xUnit.Net,那么您已经可以使用xUnit++了。

#include "xUnit++/xUnit++.h"

FACT("Foo and Blah should always return the same value")
{
    Check.Equal("0", Foo()) << "Calling Foo() with no parameters should always return \"0\".";
    Assert.Equal(Foo(), Blah());
}

THEORY("Foo should return the same value it was given, converted to string", (int input, std::string expected),
    std::make_tuple(0, "0"),
    std::make_tuple(1, "1"),
    std::make_tuple(2, "2"))
{
    Assert.Equal(expected, Foo(input));
}

主要功能:

  • 运行测试并发,非常快速。
  • 可移植性
  • 自动测试注册
  • 丰富的断言类型(Boost对xUnit++毫无优势)
  • 本地比较集合
  • 断言有三个级别:
    • 致命错误
    • 非致命错误
    • 警告
  • 易于断言日志记录:Assert.Equal(-1, foo(i)) << "Failed with i = " << i;
  • 测试日志记录:Log.Debug << "Starting test"; Log.Warn << "Here's a warning";
  • 夹具
  • 数据驱动测试(Theories)
  • 基于以下内容选择要运行的测试
    • 属性匹配
    • 名称子字符串匹配
    • 测试套件

4
这个问题要求进行比较。在我看来,至关重要的是要展示你的框架与至少两个流行框架(googletest和Boost)之间的区别,特别是如果你宣传xUnit++作为这两个框架的替代品。如果更新了的话,会得到+1评分 :) - mloskot
1
好的,我已经在wiki上有一个比较表,但我会尝试在我的回答中直接总结一些区别。 - moswald
1
我决定直接链接维基表格,把所有内容都列出来会使摘要变得混乱。 - moswald
也可以用宏语言编写。使用C++代替FACT和THEORY宏有什么问题吗? - CashCow
就我个人而言,我真的很讨厌宏。我考虑过使用方法调用和lambda编写v2.0,只是现在我不写任何C++代码,也没有时间去做这件事。 - moswald
1
你的项目已经停止了吗?最后一次提交是在09/2015...不管怎样,非常好的答案。谢谢。 - zertyz

5

CppUTest - 非常好的、轻量级的测试框架,带有模拟库。值得仔细研究。


4

CPUnit(http://cpunit.sourceforge.net)是一个类似于Google Test的框架,但它依赖更少的macos(断言是函数),并且使用前缀的宏以避免常见的宏陷阱。测试看起来像:

#include <cpunit>

namespace MyAssetTest {
    using namespace cpunit;

    CPUNIT_FUNC(MyAssetTest, test_stuff) {
        int some_value = 42;
        assert_equals("Wrong value!", 666, some_value);
    }

    // Fixtures go as follows:
    CPUNIT_SET_UP(MyAssetTest) {
        // Setting up suite here...
        // And the same goes for tear-down.
    }

}

它们自动注册,所以你不需要更多。然后只需编译和运行即可。我发现使用这个框架非常像使用JUnit,对于那些必须花费一些时间编程Java的人来说非常好用!


2

API Sanity Checker — C/C++库的测试框架:

它是一个基本单元测试的自动生成器,适用于共享的C/C++库。通过分析头文件中的声明,它能够生成合理的(在大多数情况下)输入数据和简单的(“健全”或“浅层”质量)测试用例,用于API中的每个函数。

生成的测试的质量可以检查简单使用情况下是否存在关键错误。该工具能够构建和执行生成的测试,并检测崩溃(段错误)、中止、所有种类的发射信号、非零程序返回代码和程序挂起。

与CppUnit,Boost和Google Test相比的独特功能:

  • 自动生成测试数据和输入参数(即使对于复杂数据类型)
  • 现代化且高度可重用的专业类型,而不是固定装置和模板

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接