代码约定-Visual Studio团队服务脚本化生成服务器单元测试失败

本文关键字:服务器 单元测试 失败 脚本 -Visual 约定 Studio 团队 服务 代码 | 更新日期: 2023-09-27 18:20:01

我最近将代码契约添加到了我的解决方案中。经过一些修改后,我们的构建运行没有任何问题,但由于代码合同的原因,我们的单元测试失败了。

环境:

  • 源代码管理和生成服务器托管在Visual Studio Team Service(VSTS)脚本化生成(以前的VSO)上
  • 在配置DebugRelease上启用的VS 2013高级代码(现在为VS 2015 Enterprise)合约
  • 代码协定已关闭,为自定义配置BuildServer设置了DoNotBuild标志
  • Visual Studio Team Services生成定义:
    1. 具有步骤Visual Studio
    2. 已设置标志/p:CodeContractsEnableRuntimeChecking=false;CodeContractsReferenceAssembly=false

生成服务器的错误文本示例:

试验方法Web.Tests.AccountControllerTests.CreateAccount_Pass_NoPasswordSend_Test引发异常:System.Diagnostics.Contracts.ContractException:程序集(可能是"Cms.Web")必须使用以下代码重写合约二进制重写器(CCRewrite),因为它正在调用Contract.Requires,而CONTRACTS_FULL符号为定义删除CONTRACTS_FULL符号的任何显式定义从您的项目和重建。

我已经检查了构建服务器的诊断输出,在任何地方都找不到符号CONTRACTS_FULL

我不想在构建服务器上启用代码合约,主要是因为我以前尝试过,但没有成功,而且由于时间限制,我放弃了(经过更多搜索,我得出结论,这是不可能的,因为Microsoft不允许在构建服务器上安装自定义扩展)。我只是想忽略构建服务器上的代码契约,但单元测试执行似乎无法做到这一点。

有人知道我需要在哪里寻找以确保单元测试忽略代码契约吗?看起来这应该是可能的,对吧?也许我可以在构建定义中设置另一个标志,它将被单元测试选中?


编辑

请注意,生成服务器是HOSTED在云中的Microsoft服务,是Visual Studio Team Services(以前的Visual Studio Online)的一部分。这意味着它不是我们的构建服务器,我们无法控制构建服务器上安装的内容。即便如此,我们还是希望使用代码契约。下面接受的答案是允许这样做的一种方式。

代码约定-Visual Studio团队服务脚本化生成服务器单元测试失败

请阅读代码合同手册。它告诉你需要知道的一切。您不需要在方法上定义任何ConditionalAttribute。如果您知道Contract.Requires<TException>(bool condition)的要求,则可以使用它。

正如@Mixxiphoid在他们的回答中所说,因为他们使用的是Requires的通用形式,所以代码合约需要安装在构建服务器上,并且除了调试配置之外,还需要为发布配置启用Peform运行时合约检查

如果您使用的是代码约定,则始终需要在生成调试版本的生成服务器上安装代码约定。您的团队也是如此:所有需要编译代码的开发人员都需要为调试构建安装代码合约。

这一切都在代码合同手册的第5节:使用指南中。第20页上有一个有用的图表,它对各种使用场景及其需求进行了很好的总结。


关于Contract.Requires<TException>(bool condition)

首先,为代码契约编写此方法的开发人员并没有忘记将ConditionalAttribute应用于该方法,正如接受的答案所述。远非如此。事实上,这个方法没有用该属性进行装饰,这是设计上的

如果您阅读第5节:使用指南,您会发现如果您使用这种形式的Requires方法,则需要使用二进制重写器—ccrewrite—构建程序集时。这意味着任何将构建程序集的机器都必须具有可用的ccrewrite

那么,构建您可能无法控制的服务器呢?我很高兴你问我。


TFS托管生成服务器

关于TFS托管的生成服务器:确实不能简单地在生成服务器上安装代码约定。那么你有什么选择呢?

  1. 您可以将自己限制为仅使用代码契约的"遗留"形式,if-then-throw块后面跟着Contract.EndContractBlock(),或者限制自己仅使用Contract.Requires(bool condition)(非泛型形式),或者两者的混合。
    • 在任何一种情况下,您都可能希望为TFS托管的生成服务器提供单独的调试生成配置。此生成配置将为该生成配置禁用执行运行时合同检查
  2. 你可以做一点"bining"或"谷歌搜索",得出这个搜索结果,它描述了如何在TFS Online上使用代码合约构建解决方案

链接到上面的博客文章提供了修改TFS托管生成控制器托管生成的说明。

更新:很快就会有新版本的代码合同对于那些使用托管构建服务的用户,如Visual Studio Online、AppVeyor等,新的社区驱动的代码契约GitHub repo最近发布了v1.10.xxxxx.RC1。在发布说明中,他们提到了代码契约的NuGet版本。享受

仔细检查后,此构建配置在单元测试中也存在与构建服务器上相同的错误。经过一番挖掘,我找到了答案。

答案在于Contract.Requires。方法CCD_ 17的通用版本不像非通用方法Contract.Requires那样应用属性CCD_。这意味着Contract.Requires<T>总是被评估,对此你无能为力。有关更多详细信息,请参阅Visual Studio 2010中的"尖端-代码契约设置"。

在我恢复所有代码以使用Contract.Requires而不是Contract.Requires<T>之后,我所有的单元测试都能够再次执行。您仍然可以毫无问题地使用ContractClassForContractClass属性,并在契约类中使用通用Contract.Requires<T>实现,这是因为没有CONTRACTS_FULL就无法构建契约类。

今天早上遇到了完全相同的问题。解决方案是在发布模式而不是仅在调试模式下启用运行时合同检查。

除此之外,CodeContracts还必须安装在构建服务器上。