.NET 4.0代码合同 – 它们将如何影响unit testing?

比如这篇文章介绍了他们。

有什么好处?

静态分析看起来很酷,但同时也会阻止在unit testing中将null作为parameter passing的能力。 (如果你是在文章中的例子)

关于unit testing这个话题,如果你现在已经开始进行自动化testing了,现在肯定是没有意义的。

更新

玩过代码合同,我有点失望。 例如,根据接受的答案中的代码:

public double CalculateTotal(Order order) { Contract.Requires(order != null); Contract.Ensures(Contract.Result<double>() >= 0); return 2.0; } 

对于unit testing,您仍然需要编写testing以确保不能传递null,如果合同是业务逻辑 ,则结果大于或等于零。 换句话说,如果我要删除第一份合同,除非我专门对这个function进行了testing,否则testing不会中断。 这是基于不使用内置于Visual Studio的更好(最终等)版本的静态分析。

基本上,他们都归结为写传统的if语句的替代方式。 我实际使用TDD的经验,代码合同显示了为什么,以及我如何去做。

我不认为unit testing和合同会互相干扰,如果有什么合约可以帮助unit testing,因为它不需要为无效的参数添加单调乏味的重复testing。 合约指定了函数的最小值,而unit testing试图validation特定input集的实际行为。 考虑这个人为的例子:

 public class Order { public IEnumerable Items { get; } } public class OrderCalculator { public double CalculateTotal(Order order) { Contract.Requires(order != null); Contract.Ensures(Contract.Result<double>() >= 0); return 2.0; } } 

很明显,代码满足合同,但你仍然需要unit testing来validation它实际上是否像你期望的那样。

有什么好处?

比方说,你要确保一个方法永远不会返回null 。 现在使用unit testing,你必须编写一大堆testing用例,用不同的input调用该方法,并validation输出是否为空。 麻烦的是,你不能testing所有可能的input。

使用代码契约,你只需声明该方法永远不会返回null 。 如果不能certificate这一点,静态分析仪将会发出抱怨。 如果它不抱怨,你知道你的断言是正确的所有可能的投入。

更less的工作,完美的正确性保证。 什么是不喜欢?

合同允许你说出代码的实际目的是什么,而不是让任何代码做什么,随机的参数是否从编译器的angular度来看,或者是下一个代码读者的定义。 这允许显着更好的静态分析和代码优化。

例如,如果我声明一个整数参数(使用约定符号)在1到10的范围内,并且我的函数中有一个局部数组被声明为相同的大小,并且被参数索引,编译器可以告诉没有下标错误的可能性,从而产生更好的代码。

您可以声明null是合约中的有效值。

unit testing的目的是dynamic地validation代码是否达到了所规定的目的。 仅仅因为你已经写了一个函数的合同,并不意味着代码就这么做了,或者说静态分析可以validation代码是这样做的。 unit testing不会消失。

那么它不会干扰一般的unit testing。 但是正如我所看到的你提到了TDD的一些事情。

如果我从这个angular度思考这个问题,我想它可能/可能会改变标准程序

  • 创build方法(只是签名)
  • 创buildunit testing – >执行testing
  • 运行testing:让它失败
  • 实施该方法,只是为了使其工作而将其破解
  • 运行testing:看看它通过
  • 重构你的(可能是凌乱的)方法体
  • (重新运行testing只是为了看看你没有损坏任何东西)

这将是真正的function齐全的unit testing程序。 在这样的背景下,我想你可以在第一点和第二点之间插入代码契约

  • 创build方法(只是签名)
  • 为方法input参数插入代码合同
  • 创buildunit testing – >执行testing

我目前所看到的优点是,您可以编写更简单的unit testing,因为您不必检查每条可能的path,因为已经通过您定义的合同考虑了一些path。 它只是给你额外的检查,但它不会取代unit testing,因为代码中总是会有更多的逻辑,更多的path必须像往常一样用unit testing来testing。

编辑

我之前没有考虑的另一种可能性是将代码合约添加到重构部分中。 基本上作为确保事物的附加方式。 但是,这将会是多余的,因为人们不喜欢做冗余的东西…