测试用例和断言陈述

时间:2008-09-11 09:53:28

标签: defensive-programming

this question中的代码让我想到了

assert(value>0); //Precondition
if (value>0)
{
  //Doit
}

我从不写if语句。断言就足够/您可以做的所有事情。 “早点崩溃,经常崩溃”

CodeComplete州:

  • assert-statement使应用程序正确
  • if-test使应用程序健壮

我不认为您通过更正无效输入值或跳过代码使应用程序更加健壮:

assert(value >= 0 );  //Precondition
assert(value <= 90);  //Precondition
if(value < 0)         //Just in case
  value = 0;
if (value > 90)       //Just in case
  value = 90;
//Doit

这些更正是基于您对外部世界的假设。 只有调用者知道你的函数的“有效输入值”是什么,并且他必须在调用你的函数之前检查它的有效性。

CodeComplete来解释: “当我们完全依赖断言时,真实世界的程序变得太乱了。”

问题:我错了,顽固,愚蠢,太不防守......

9 个答案:

答案 0 :(得分:10)

信任Asserts的问题在于它们可能在生产环境中被关闭。引用维基百科文章:

  

大多数语言都允许断言   全局启用或禁用,以及   有时独立。断言   通常在开发期间启用   在最终测试期间和   在向客户发布时不   检查断言以避免成本   评估断言的同时,   假设断言没有   副作用,仍然产生相同的   结果在正常情况下。下   异常情况,禁用   断言检查可能意味着a   会中止的程序会   继续跑。这有时候   优选的。   Wikipedia

因此,如果您的代码的正确性依赖于Asserts,那么您可能会遇到严重的问题。当然,如果代码在测试期间工作,它应该在生产期间工作...现在进入第二个工作代码的人,只是要解决一个小问题......

答案 1 :(得分:4)

使用断言来验证您控制的输入:私有方法等。

使用if语句验证您无法控制的输入:设计用于用户使用的公共接口,用户输入测试等。

使用内置的断言测试应用程序。然后在没有断言的情况下进行部署。

答案 2 :(得分:3)

在某些情况下,构建发布时会断言断言。您可能无法控制它(否则,您可以使用断言构建),因此最好这样做。

“纠正”输入值的问题在于调用者无法获得他们所期望的内容,这可能会导致程序完全不同的部分出现问题甚至崩溃,从而使调试成为一场噩梦。

我经常在if语句中抛出一个异常,以便在它们被禁用的情况下接管assert的角色

assert(value>0);
if(value<=0) throw new ArgumentOutOfRangeException("value");
//do stuff

答案 3 :(得分:2)

我不同意这句话:

  

只有来电者知道什么是“有效的   输入值“是为你的功能,和   他必须在他之前检查其有效性   调用你的功能。

来电者可能认为他知道输入值是正确的。只有方法作者知道它如何工作。程序员的最佳目标是让客户陷入“pit of success”。在特定情况下,您应该确定哪种行为更合适。在某些情况下,可以原谅不正确的输入值,在其他情况下,您应该抛出异常\返回错误。

对于Asserts,我会重复其他评论者,断言是代码作者的 debug 时间检查,而不是代码客户端。

答案 4 :(得分:1)

如果我从CS-class中正确记得

前提条件定义函数输出定义的条件。如果使函数处理错误条件,则为这些条件定义函数,并且不需要断言语句。

所以我同意。通常你不需要两者。

正如Rik评论的那样,如果在已发布的代码中删除断言,这可能会导致问题。通常我不会这样做,除非在性能关键的地方。

答案 5 :(得分:1)

不要忘记大多数语言都允许你关闭断言......就个人而言,如果我准备编写测试以防止所有范围的无效输入,我不会打扰首先是断言。

另一方面,如果你没有编写逻辑来处理所有情况(可能是因为尝试继续使用无效输入是不明智的)那么我将使用断言语句并进行“早期失败”方法

答案 6 :(得分:0)

对于仅供您使用的内部功能,仅使用断言。断言将有助于在测试期间捕获错误,但不会妨碍生产中的性能。

使用 if-conditions 检查外部发起的输入。从外部来看,这是您/您的团队控制和测试的代码之外的任何地方。

您可以选择两者。这将是面向外部的功能,其中集成测试将在生产之前完成。

答案 7 :(得分:0)

我应该说我知道断言(这里)在生产代码中消失了。

如果if语句实际纠正了生产代码中的无效输入数据,这意味着断言在测试调试代码期间从未停止过,这意味着您编写的代码从未执行过。

对我而言,这是一种情况:

(引用安德鲁)“防止所有无效输入范围,我首先不打扰这个断言。” - &GT;写一个if-test。

(引用aku)“不正确的输入值可以原谅” - &gt;写一个断言。

我不能站在两个......

答案 8 :(得分:-1)

断言的一个问题是它们可以(并且通常会)从代码中编译出来,所以你需要添加两个墙,以防编译器抛弃它们。