Reputation: 62213
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:
Debug
and Release
DoNotBuild
flag set for custom configurations BuildServer
/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.
Upvotes: 2
Views: 1595
Reputation: 4234
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.
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.
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?
Contract.EndContractBlock()
or limit yourself to only using Contract.Requires(bool condition)
(the non-generic form), or a mixture of the two.
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.
Upvotes: 6
Reputation: 62213
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
.
Upvotes: 4
Reputation: 1034
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.
Upvotes: 1