单元测试是否不需要Debug.Assert()?

时间:2009-05-04 19:54:36

标签: c# unit-testing

我已经准备好了Mcconnell的“Code Complete”。现在我在Hunt& amp;托马斯的“The Pragmatic Programmer”:使用断言! 注意:不是单元测试断言,我的意思是Debug.Assert()

遵循SO问题When should I use Debug.Assert()?When to use assertion over exceptions in domain classes断言对于开发很有用,因为“不可能”的情况可以很快找到。它们似乎很常用。据我理解的断言,在C#中,它们通常用于检查输入变量的“不可能”值。

为了尽可能简化和隔离单元测试,我使用null和“不可能”的虚拟输入(如空字符串)来提供类和方法。

此类测试明确记录,它们不依赖于某些特定输入。 注意:我正在练习Meszaros的“xUnit测试模式”描述为Minimal Fixture

这就是重点:如果我有一个保护这些输入的断言,它们会炸毁我的单元测试。

我喜欢断言编​​程的想法,但另一方面我不需要强迫它。目前我无法想到Debug.Assert()的任何用途。也许有一些我想念的东西?你有什么建议,他们可能真的有用吗?也许我只是高估了断言的用处?或者我的测试方式可能需要重新考虑?

编辑:Best practice for debug Asserts during Unit testing非常相似,但它没有回答困扰我的问题:如果我按照我的描述进行测试,我是否应该关心C#中的Debug.Assert()?如果是的话,在哪种情况下他们真的有用吗?在我目前的观点中,这样的单元测试会使Debug.Assert()变得不必要。

另一点:如果你真的这么认为,这是一个重复的问题,只需发表一些评论。

5 个答案:

答案 0 :(得分:5)

理论上,你是对的 - 详尽的测试使断言多余。理论上。在parctice中,它们仍然可用于调试测试,以及捕获可能尝试使用不符合其预期语义的接口的未来开发人员的尝试。

简而言之,它们只是用于单元测试的不同目的。他们在那里捕捉错误,这些错误本质上是在编写单元测试时不会产生的。

我建议保留它们,因为它们可以提供程序员错误的另一级保护。

它们也是本地错误保护机制,而单元测试在被测试代码的外部。在压力下“无意中”禁用单元测试比在一段代码中禁用所有断言和运行时检查要容易得多。

答案 1 :(得分:4)

我通常看到断言用于对内部状态进行健全性检查,而不是像参数检查那样。

IMO应该通过检查保护固体API的输入,而不管构建类型如何。例如,如果公共方法需要一个介于5和500之间的数字的参数,则应该使用ArgumentOutOfRangeException进行保护。就我而言,快速失败并经常使用异常失败,特别是当某个参数被推到某个地方并且以后使用时。

但是,在对内部瞬态进行完整性检查的地方(例如,在循环期间检查某个中间状态是否在合理范围内),似乎Debug.Assert更像是在家里。尽管传递了有效的参数,但当你的算法出错时,你还打算做什么?抛出EpicFailException? :)我认为这是Debug.Assert仍然有用的地方。

我仍未决定两者之间的最佳平衡。自从我开始进行单元测试以来,我已经停止在C#中使用Debug.Asserts了,但是他们仍然有一个地方给他们IMO。我当然不会用它们来检查API使用的正确性,但是很难检查到理智的地方?当然。

唯一的缺点是它们可以弹出并暂停NUnit,但你可以编写一个NUnit插件来检测它们,并且无法触发断言的任何测试。

答案 2 :(得分:3)

我正在使用单元测试和断言,用于不同的目的。

单元测试是自动化实验,显示您的程序(及其部件)按指定的方式运行。就像在数学中一样,只要你不能尝试所有可能的输入组合,实验就不是证据。没有什么能比使用单元测试更好的事实证明你的代码会有bug。并不多,但会有它们。

断言用于在运行时捕捉通常不应发生的狡猾情况。也许你已经听说过前置条件,后置条件,循环不变量等等。在现实世界中,如果满足前提条件,我们通常不会经历(通过形式逻辑)实际证明一段代码产生指定的后置条件的正式过程。这将是一个真正的数学证明,但我们通常没有时间为每种方法做到这一点。但是,通过检查先决条件和后置条件是否得到满足,我们可以在更早的阶段发现问题。

答案 3 :(得分:2)

如果您正在进行详尽的单元测试,其中涵盖了您可能遇到的所有奇怪边缘情况,那么我认为您不会发现断言非常有用。大多数没有进行单元测试的人都会断言,以便在测试时发现类似的约束。

答案 4 :(得分:1)

我认为在这种情况下单元测试背后的想法是将这些断言移到测试用例上,以确保不会让Debug.Assert(...)代码处理它而不会抛出(或确保)它正确地呕吐了。)