简体   繁体   中英

Code Contracts - Visual Studio Team Service Scripted Build Server Unit Tests Fail

I recently added Code Contracts to my solution. After some modifications our build runs without any problems but our unit tests fail because of Code Contracts.

Environment:

  • Source control and build server are hosted on Visual Studio Team Service (VSTS) Scripted Build ( formerly VSO )
  • VS 2013 Premium Code ( now VS 2015 Enterprise ) contracts enabled on configurations Debug and Release
  • Code contract turned off with DoNotBuild flag set for custom configurations BuildServer
  • Visual Studio Team Services build definition:
    1. Has step Visual Studio
    2. has flags set /p:CodeContractsEnableRuntimeChecking=false;CodeContractsReferenceAssembly=false

Example error text from build server:

Test method Web.Tests.AccountControllerTests.CreateAccount_Pass_NoPasswordSend_Test threw exception: System.Diagnostics.Contracts.ContractException: An assembly (probably "Cms.Web") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.Requires and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild.

I have examined the diagnostic output from the build server and there is no symbol CONTRACTS_FULL that can be found anywhere.

I do not want to enable code contracts on the build server mostly because I had tried that before with no success and due to time constraints I gave up ( after more searching I came to the conclusion that this is not possible as Microsoft does not allow for custom extensions to be installed on the build server ). I simply want to ignore code contracts on the build server but the Unit Test execution does not seem to do this.

Any one have any ideas on where I need to look to ensure code contracts are ignored by the unit tests? Seems like this should be possible right? Maybe there is another flag I could set in the build definition that will be picked up by the unit tests?


Edit

Please note the build server is HOSTED in the cloud as a Microsoft service as a part of Visual Studio Team Services (formerly Visual Studio Online). This means it is not our build server, we have no control over what is installed on the build server. Even so we want to use Code Contracts. The accepted answer below is a way to allow for this.

Please, please read the Code Contracts manual. It tells you everything you need to know. You don't need any ConditionalAttribute defined on your methods. You can use Contract.Requires<TException>(bool condition) if you know what the requirements for doing so are.

As @Mixxiphoid said in their answer, because they were using the generic form of Requires, Code Contracts is required to be installed on the build server and Peform Runtime Contract Checking needs to be enabled for the Release configuration in addition to the Debug configuration.

If you are using Code Contracts, then you will always need Code Contracts installed on the build servers that build Debug releases. The same goes for your team: all developers who need to compile the code will be required to have Code Contracts installed for Debug builds.

It's all in Section 5: Usage Guidelines in the Code Contracts manual. There's a helpful diagram on page 20 that gives a great summary of the various usage scenarios and their requirements.


About Contract.Requires<TException>(bool condition)

First off, the developer that wrote this method for Code Contracts did not forget to apply the ConditionalAttribute to the method, as the accepted answer states. Far from it. The very fact that this method is not decorated with that attribute is by design .

If you read Section 5: Usage Guidelines , you see that if you use this form of the Requires method, then you are required to use the binary rewriter— ccrewrite —when building your assembly. This implies that any machine which will build your assembly must have ccrewrite available.

So, what about build servers that you may not control? I'm glad you asked.


TFS Hosted Build Servers

With respect to TFS hosted build servers: It's true that you cannot simply install Code Contracts on the build servers. So what are your options?

  1. You could limit yourself to using only the "legacy" form of code contracts, if-then-throw blocks followed by Contract.EndContractBlock() or limit yourself to only using Contract.Requires(bool condition) (the non-generic form), or a mixture of the two.
    • In either case, you'll probably want to have a separate Debug build configuration for the TFS-hosted build server. This build configuration would have Perform Runtime Contract Checking disabled for that build configuration.
  2. You could do a little "bing-ing" or "googling" and come up with this search result, which describes how to enable building your solution with Code Contracts on TFS Online.

The blog post linked to above has instructions for modifying a TFS Hosted Build Controller hosted build.

UPDATE: THERE WILL SOON BE A NUGET VERSION OF CODE CONTRACTS For those of you using hosted build services, such as Visual Studio Online, AppVeyor, etc., the new community-driven Code Contracts GitHub repo recently announced v1.10.xxxxx.RC1 . In the release notes, they mention a NuGet version of code contracts . Enjoy.

After double checking this build configuration also has the same errors in the unit test as on the build server. After some digging I came up with the answer.

The answer lies in Contract.Requires . The generic version of method Contract.Requires<T> does not apply the attribute [Conditional("CONTRACTS_FULL")] where as the non-generic method Contract.Requires does. This means that Contract.Requires<T> is always evaluated and there is nothing you can do about it. See Cutting Edge - Code Contracts Settings in Visual Studio 2010 for more detail.

After I reverted all of my code to make use of Contract.Requires instead of Contract.Requires<T> all my unit tests were able to execute again. You can still make use of ContractClassFor and ContractClass attributes and make use of the generic Contract.Requires<T> implementation within the contract class without any problem, this because the contract class will not get built without CONTRACTS_FULL .

Got the exact same problem this morning. The solution was to enable runtime contract checking on release mode instead of only debug mode.

Beside that, CodeContracts had to be installed on the build server as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM