【问题标题】:Design by contract and unit testing in C++契约式设计和 C++ 中的单元测试
【发布时间】:2012-11-20 00:27:52
【问题描述】:

我正在尝试在应用程序中结合基本的契约式设计(由宏实现,使用内置的断言函数)和 Google 测试单元测试。

所以,例如,我有以下代码:

AppFavorite* AppFavorites::Add(const UnicodeString& link)
{
    REQUIRE(!link.IsEmpty());

    ...
}

现在,我的单元测试中不能进行以下测试,因为 IDE 在到达断言时中止 (REQUIRE(!link.IsEmpty());):

TEST(AppFavoritesTest, AddEmpty)
{
    AppFavorites favorites;
    ASSERT_THROW(favorites.Add(L""), std::invalid_argument);
}

所以,我的问题是我应该:

  1. 切勿测试合同涵盖的条件,或
  2. 在单元测试期间以某种方式禁用合同检查?

【问题讨论】:

    标签: c++ unit-testing c++builder googletest design-by-contract


    【解决方案1】:

    您需要决定是否将空字符串传递给该函数是未定义的行为,或者它是否保证在传递空字符串时它会引发异常。

    听起来你的意图是让它成为未定义的行为,即合同没有说明如果传递一个空字符串会发生什么。在这种情况下,测试合同验证的最简单方法是构建用于负测试的单元测试作为特殊构建,并修改 REQUIRE 以抛出一些“违反前提条件”异常,然后您将使用 @987654323 进行测试@

    我强烈推荐观看John Lakos' talk on Defensive Programming from ACCU 2011,它正好解决了这个问题

    【讨论】:

      【解决方案2】:

      按合同设计定义了法律。每次使用您的软件都必须遵守这些法律——包括其单元测试。单元测试测试,提供软件满足法律,它也做你想让它做的事情。

      所以你应该只在满足前提条件的情况下测试你的软件。

      在任何用户都可能以错误方式使用的公共层中,最好激活前置条件检查,或者使用特殊的输入验证层保护您的输入,然后使用各种可能的输入数据进行测试,包括您的内部逻辑认为违反先决条件的内容 - 但是您将测试的是保护层。

      我发现遵循这一策略的软件构建从长远来看更加健壮和可维护。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多