如何配置Pex以遵守代码契约?

7

在以下示例代码中,我该如何配置Pex以尊重我的Code Contracts?

    public static IEnumerable<User> Administrators(this UserGroup userGroup)
    {
        Contract.Requires(userGroup != null);
        Contract.Requires(userGroup.UserList != null);

        return userGroup.UserList.Where(ul => ul.IsAdmin == true);
    }

当前问题:当我运行Pex时,它仍在生成违反指定代码合同的测试用例。
FYI:这是我的csproj文件中的“代码合同”设置

编辑: SP1中发生了什么故障


你试过给他们发电子邮件吗?pexbug@microsoft.com - porges
2
我认为这是一个错误。John Nicholas的解决方案可以工作,但对于PEX来说仍然不是正确的行为。使用代码合同与pex的重点在于PEX自动捕捉代码合同并将其失败视为预期行为或通过测试。 - Joshua Dale
5个回答

4

首先,您需要使用一个类型化版本的Requires。

将ArgumentNullException用作T。

此外,在您的项目属性中,您需要告诉代码契约使用标准重写器。不要在失败时点击断言;)

Contract.Requires<ArgumentNullException>(i != null);

如果您的代码出现参数为空异常,Pex 可以向您的 PexMethod 添加一个属性,说明允许抛出该异常,并创建一个通过抛出该异常的测试。

然后,您可以推广这些更改并保存单元测试。


+1:非常感谢!“失败时断言”设置让我遇到了很大的麻烦。 - Jim G.
1
是的,我也花了几个小时在键盘上猛敲那个问题。 ;) - John Nicholas
我认为这只是一个权宜之计,而不是解决方案。我认为这个解决方案可能无法检测到真正的“ArgumentNullException”,因为它可能会从被测试代码中的其他地方抛出。在我的答案中,我提出了一种替代方案,它没有这个问题。 - lexicalscope
不同意那段代码只处理它自己的异常...应该将其向上传递。 - John Nicholas

3
它有意违反合同以验证违反合同时是否会抛出异常。很多人会在发布版本中编译掉“Requires”方法,但有些人认为应该仍处理边缘情况。还可以编写自定义合同失败处理程序,它可能不会引发异常或断言失败。如果您有一个自定义的合同失败处理程序,它不会阻止进一步执行,那么您可能会导致更大的问题发生。Pex所做的是编写违反合同的测试,以便在抛出异常时通过测试。 简而言之,你不必担心这个问题。

谢谢提供信息,Bryan。不过我有个问题 - 我能否告诉 Pex 预期异常,并在违反合同时将该测试标记为绿色? - Jim G.
如果合同抛出断言或异常,Pex应该自动标记测试为绿色,表示违反了合同。 - Bryan Anderson
应该可以,但我认为当前的实现有问题。我目前遇到了一个问题。https://dev59.com/zW025IYBdhLWcg3wtoRA - Joshua Dale
@Joshua Dale:@John Nicholas 的解决方案对我有用。请试一试。 - Jim G.
2
这是一个修复,但仍然不是正确的行为。测试应该自动捕捉代码合同并将失败视为预期行为。 - Joshua Dale

1
我还需要打开Contract Reference Assembly来进行构建(我也发出了XML文档文件,以便在VS中查看合同)。
这似乎是Pex理解合同所必需的。

1

我曾有过同样的问题。有两个要点:

1)检查运行时重写是否已启用(如John所建议的)

2)确保您的测试类被装饰了[PexClass(typeof(MyClass))]。

我手动编写了测试代码,因此忘记了PexClass属性,而且合同被Pex视为常规异常,因此它们失败了。

Honza


0

有一个属性PexAllowedContractRequiresFailure,您可以将其应用于测试方法,以告诉Pex不生成导致要求失败的测试。

您还必须在解决方案属性中启用“执行运行时合同检查”。

[TestClass]
public partial class MyTest
{
   [PexMethod]
   [PexAllowedContractRequiresFailure]
   public void TestMethod(int myParam)
   {
      Contract.Requires(myParam > 5);
      ...
   }
}

还有相关的PexAllowedContractRequiresFailureAtTypeUnderTestSurface,如果您希望Pex尊重的“Requires”更深入调用树,则可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接