测试用例和断言声明
这个问题中的代码让我思考
assert(value>0); //Precondition if (value>0) { //Doit }
我从不写if语句。声明就足够了/我们可以做的一切。
"早期崩溃,经常崩溃"
CodeComplete状态:
- 声明语句使应用程序正确
- 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:
"当我们不仅仅依赖于断言时,现实世界的程序就会变得太混乱了。"
问题:我错了,顽强,愚蠢,太缺乏防御性了吗?
解决方案
回答
仅信任断言的问题在于它们可能在生产环境中被关闭。引用维基百科文章:
Most languages allow assertions to be enabled or disabled globally, and sometimes independently. Assertions are often enabled during development and disabled during final testing and on release to the customer. Not checking assertions avoiding the cost of evaluating the assertions while, assuming the assertions are free of side effects, still producing the same result under normal conditions. Under abnormal conditions, disabling assertion checking can mean that a program that would have aborted will continue to run. This is sometimes preferable. Wikipedia
因此,如果代码的正确性依赖于Asserts,那么我们可能会遇到严重的问题。当然,如果代码在测试中起作用了,那么它应该在生产中起作用...现在输入第二个可以处理该代码的家伙,这将解决一个小问题...
回答
在某些情况下,在构建发行版时断言被禁用。我们可能对此没有控制权(否则,可以使用asserts进行构建),因此这样做是个好主意。
"校正"输入值的问题在于,调用者将无法获得他们期望的结果,这可能导致程序的完全不同部分出现问题甚至崩溃,从而使调试成为一场噩梦。
我通常在if语句中引发异常,以在断言被禁用的情况下取代断言的角色
assert(value>0); if(value<=0) throw new ArgumentOutOfRangeException("value"); //do stuff
回答
如果我没记错CS级的话
前提条件定义在什么条件下定义函数的输出。如果使函数处理错误条件,则将为这些条件定义函数,并且不需要assert语句。
所以我同意。通常,我们不需要两者。
正如Rik所说,如果删除已发布代码中的断言,这可能会导致问题。通常,除了在性能至关重要的地方,我不会这样做。
回答
断言的一个问题是它们可以(并且通常会)从代码中进行编译,因此我们需要添加两堵墙,以防编译器扔掉它们。
回答
不要忘记,大多数语言都允许我们关闭断言...就我个人而言,如果我准备编写测试以防止所有范围的无效输入的情况,那么我一开始就不会打扰断言。
另一方面,如果我们没有编写处理所有情况的逻辑(可能是因为尝试继续无效的输入并不明智),那么我将使用断言语句并采用"早期失败"方法。
回答
对于内部函数,只有我们将要使用的内部函数只能使用断言。这些断言将有助于在测试期间捕获错误,但不会影响生产性能。
检查具有if条件的外部输入。从外部看,这是我们/团队控制和测试的代码之外的任何地方。
(可选)我们可以同时拥有两者。这将用于面向外部的功能,这些功能将在生产之前进行集成测试。
回答
我不同意这一说法:
Only the caller knows what "a valid input value" is for your function, and he must check its validity before he calls your function.
呼叫者可能认为他知道输入值正确。只有方法作者知道它应该如何工作。程序员的最佳目标是使客户陷入"成功之坑"。我们应确定在特定情况下哪种行为更合适。在某些情况下,错误的输入值是可以原谅的,在其他情况下,我们应该抛出异常\返回错误。
至于Asserts,我会重复其他评论者,assert是针对代码作者而不是代码客户端的调试时间检查。
回答
我应该说过,我知道断言(在这里)在生产代码中消失的事实。
如果if语句实际上纠正了生产代码中的无效输入数据,则意味着断言在调试代码的测试期间永远不会出错,这意味着我们编写了从未执行的代码。
对我来说,这是一个OR情况:
(引用安德鲁)"防止所有范围的无效输入,我一开始就不会理会断言。" ->编写一个if-test。
(引用aku)"错误的输入值是可以原谅的"->写一个断言。
我都受不了...
回答
使用断言来验证我们控制的输入:私有方法等。
使用if语句来验证我们无法控制的输入:设计用于用户使用的公共接口,用户输入测试等。
使用内置的断言测试应用程序。然后在不使用断言的情况下进行部署。