38

例如本文介绍了它们。

有什么好处?

静态分析看起来很酷,但同时它会阻止在单元测试中将 null 作为参数传递的能力。(如果您按照文章中的示例进行操作)

在单元测试的话题上——考虑到现在的情况,如果你已经练习过自动化测试,那么代码合同肯定没有意义吗?

更新

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

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

对于单元测试,你还是要写测试保证null不能通过,如果合约是业务逻辑,结果大于等于0 。换句话说,如果我要删除第一个合同,任何测试都不会中断,除非我专门对此功能进行了测试。然而,这是基于不使用更好(终极等)版本的 Visual Studio 中内置的静态分析。

从本质上讲,它们都归结为编写传统 if 语句的另一种方式。我实际使用TDD 和 Code Contracts的经验说明了为什么,以及我是如何去做的。

4

4 回答 4

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;
    }
}

显然,代码满足合同要求,但您仍然需要进行单元测试来验证它的实际行为是否符合您的预期。

于 2009-09-05T15:35:03.650 回答
27

有什么好处?

假设您要确保方法永远不会返回null。现在使用单元测试,您必须编写一堆测试用例,在其中调用具有不同输入的方法并验证输出不为空。麻烦的是,您无法测试所有可能的输入。

使用代码契约,您只需声明该方法永远不会返回null。如果无法证明这一点,静态分析器就会抱怨。如果它没有抱怨,您就知道您的断言对于所有可能的输入都是正确的。

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

于 2009-09-06T00:17:30.450 回答
4

契约允许你说出代码的实际目的是什么,而不是让代码用任何随机参数做的任何事情都被交给它作为从编译器或代码的下一个读者的角度来看的定义。这允许显着更好的静态分析和代码优化。

例如,如果我声明一个整数参数(使用合同表示法)在 1 到 10 的范围内,并且我的函数中有一个本地数组声明了相同的大小,由参数索引,编译器可以告诉没有下标错误的可能性,从而产生更好的代码。

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

单元测试的目的是动态验证代码是否达到了它所声明的目的。仅仅因为您已经为函数编写了合约,并不意味着代码会这样做,或者静态分析可以验证代码是否这样做。单元测试不会消失。

于 2009-09-05T15:23:17.093 回答
3

好吧,它通常不会干扰单元测试。但正如我所见,您提到了一些关于 TDD 的内容。

如果我从这个角度考虑它,我想它可能/可能会改变标准的程序

  • 创建方法(只是签名)
  • 创建单元测试 -> 实施测试
  • 运行测试:让它失败
  • 实施该方法,将其破解到最后只是为了使其正常工作
  • 运行测试:看到它通过
  • 重构你的(可能是混乱的)方法体
  • (重新运行测试只是为了看看你没有破坏任何东西)

这将是真正困难的全功能单元测试过程。在这种情况下,我想您可以在第一点和第二点之间插入代码合同,例如

  • 创建方法(只是签名)
  • 为方法输入参数插入代码契约
  • 创建单元测试 -> 实施测试
  • ...

我目前看到的优势是您可以编写更简单的单元测试,因为您不必检查所有可能的路径,因为您定义的合同已经考虑了一些路径。它只是为您提供额外的检查,但它不会取代单元测试,因为代码中总会有更多的逻辑,更多的路径必须像往常一样使用单元测试进行测试。

编辑

我之前没有考虑过的另一种可能性是在重构部分添加代码协定。基本上作为保证事情的额外方式。但这在某种程度上是多余的,因为人们不喜欢做多余的事情......

于 2009-09-05T15:43:28.160 回答