代码约定 - Visual Studio Team Service脚本构建服务器单元测试失败

时间:2014-08-30 11:17:25

标签: c# visual-studio-2013 code-contracts azure-devops

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

环境:

  • 源代码控制和构建服务器托管在Visual Studio Team Service(VSTS)脚本构建(以前的VSO
  • 在配置DebugRelease
  • 上启用了VS 2013 Premium Code( now VS 2015 Enterprise )合同
  • 代码合约已关闭,并为自定义配置DoNotBuild
  • 设置了BuildServer标记
  • Visual Studio Team Services构建定义:
    1. 有步骤Visual Studio
    2. 已设置标记/p:CodeContractsEnableRuntimeChecking=false;CodeContractsReferenceAssembly=false

来自构建服务器的示例错误文本:

  

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

我已经检查了构建服务器的诊断输出,并且没有可以在任何地方找到的符号CONTRACTS_FULL

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

任何人对我需要查看的位置有任何想法,以确保单元测试忽略代码合同?看起来这应该是可能的吗?也许我可以在构建定义中设置另一个标志,它将被单元测试选中?


修改

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

3 个答案:

答案 0 :(得分:6)

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

正如@Mixxiphoid在答案中所说,因为他们使用的是通用形式的Requires,所以需要在构建服务器上安装代码契约 Peform Runtime Contract Checking 调试配置外,还需要为Release配置启用。

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

全部在“代码合同”手册中的第5部分:使用指南中。 第20页上有一个有用的图表,可以很好地总结各种使用方案及其要求。

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

首先,为代码合同 编写此方法的开发人员 忘记将ConditionalAttribute应用于该方法,正如接受的答案所述。离得很远。该方法未使用该属性修饰的事实是 按设计

如果您阅读第5部分:使用指南,您会看到如果您使用Requires方法的此形式,那么您需要使用二进制重写器 - {{1} - 建立你的装配时。这意味着任何构建程序集的机器都必须ccrewrite可用。

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

TFS托管构建服务器

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

  1. 您可以将自己限制为仅使用“遗留”形式的代码合同, if-then-throw 块后跟ccrewrite或仅限于使用Contract.EndContractBlock() (非通用形式),或两者的混合。
    • 在任何一种情况下,您可能都希望为TFS托管的构建服务器提供单独的Debug构建配置。此构建配置将为该构建配置禁用执行运行时合同检查
  2. 您可以做一些“bing-ing”或“Google搜索”并提出this搜索结果,其中介绍了如何在TFS Online上使用代码合同构建解决方案。
  3. 上面链接的博客文章提供了修改TFS托管构建控制器托管构建的说明。

    更新:代码合约的数量很大 对于那些使用托管构建服务的人,例如Visual Studio Online,AppVeyor等,新的社区驱动的Code Contracts GitHub repo最近宣布 v1.10.xxxxx.RC1 。在发行说明中,他们提到NuGet version of code contracts。享受。

答案 1 :(得分:4)

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

答案在于Contract.Requires。方法Contract.Requires<T>的通用版本不会将属性[Conditional("CONTRACTS_FULL")]应用于非泛型方法Contract.Requires。这意味着始终会评估Contract.Requires<T>,并且您无法对其进行任何操作。有关详细信息,请参阅Cutting Edge - Code Contracts Settings in Visual Studio 2010

我恢复了所有代码以使用Contract.Requires代替Contract.Requires<T>后,所有单元测试都能够再次执行。您仍然可以使用ContractClassForContractClass属性并在合同类中使用通用Contract.Requires<T>实现而没有任何问题,这是因为合同类不会在没有{{{ 1}}。

答案 2 :(得分:1)

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

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