2

我正在尝试在应用程序中结合基本的按合同设计(由使用内置断言函数的宏实现)和 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. 在单元测试期间以某种方式禁用合同检查?
4

2 回答 2

5

您需要确定将空字符串传递给该函数是否是未定义的行为,或者如果传递一个空字符串,它的合同是否保证它会引发异常。

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

我强烈推荐观看John Lakos 在 ACCU 2011 上关于防御性编程的演讲,它正好涵盖了这个问题

于 2012-11-20T00:38:55.490 回答
1

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

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

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

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

于 2013-02-11T08:46:20.520 回答