例如,这个article介绍了它们。
有什么好处?
静态分析似乎很酷但同时它会阻止在单元测试中将null作为参数传递的能力。 (如果您按照文章中的示例进行操作)
关于单元测试的主题 - 如果您已经实施自动化测试,那么现在确定代码合同没有意义吗?
更新
玩过代码合约后,我有点失望。例如,根据接受的答案中的代码:
public double CalculateTotal(Order order)
{
Contract.Requires(order != null);
Contract.Ensures(Contract.Result<double>() >= 0);
return 2.0;
}
对于单元测试,仍然必须编写测试以确保无法传递null,并且如果合同是业务逻辑。换句话说,如果我要删除第一个合同,除非我特意测试了这个功能,否则没有测试会中断。这是基于不使用内置于Visual Studio的更好(终极等)版本中的静态分析。
基本上,他们都归结为编写传统if语句的另一种方式。我实际使用TDD, with Code Contracts的经验说明了原因,以及我如何使用它。
答案 0 :(得分:38)
我不认为单元测试和合同会相互干扰那么多,如果有任何合同应该帮助单元测试,因为它不需要为无效参数添加繁琐的重复测试。合同指定了函数的最小值,而单元测试则尝试验证特定输入集的实际行为。考虑这个人为的例子:
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;
}
}
显然,代码符合合同,但您仍然需要单元测试来验证它实际上是否符合您的预期。
答案 1 :(得分:27)
有什么好处?
假设您要确保方法永远不会返回null
。现在使用单元测试,您必须编写一组测试用例,您可以使用不同的输入调用方法,并验证输出不为null。 麻烦的是,您无法测试所有可能的输入。
使用代码契约,您只需声明该方法永远不会返回null
。如果无法证明这一点,静态分析仪会抱怨。如果没有抱怨,您知道您的断言对于所有可能的输入都是正确的。
减少工作量,完美正确保证。什么不喜欢?
答案 2 :(得分:4)
契约允许你说出代码的实际目的是什么,而不是让代码用任何随机参数做什么,从编译器或者下一个读者的角度来看它作为定义。码。这样可以显着改善静态分析和代码优化。
例如,如果我声明一个整数参数(使用合约表示法)在1到10的范围内,并且我在我的函数中声明了相同大小的本地数组,该参数由参数索引,编译器可以判断出没有下标错误的可能性,从而产生更好的代码。
您可以声明null是合同中的有效值。
单元测试的目的是验证动态地代码实现其具有的任何声明目的。仅仅因为您已经为函数编写了一个契约,并不意味着代码会这样做,或者静态分析可以验证代码是否这样做。单元测试不会消失。
答案 3 :(得分:3)
一般来说,它不会干扰单元测试。但正如我所见,你提到了一些关于TDD的事情。
如果我从这个角度思考它,我想它可能/可能会改变标准的程序
这将是真正功能齐全的单元测试程序。在这样的上下文中,我猜你可以在第一点和第二点之间插入代码契约,如
我目前看到的优势是,您可以编写更简单的单元测试,因为您不必检查每条可能的路径,因为已定义的合同已经考虑了某些路径。它只是给你额外的检查,但它不会取代单元测试,因为代码中总会有更多的逻辑,更多的路径必须像往常一样用单元测试进行测试。
我之前没有考虑的另一种可能性是在重构部分添加代码契约。基本上作为确保事情的额外方式。但这在某种程度上是多余的,因为人们不喜欢做多余的事情......