Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debug.Assert vs Code Contract usage

When should I debug.assert over code contracts or vice versa? I want to check precondition for a method and I am confused to choose one over the other. I have unit tests where I want to test failure scenarios and expect exceptions.

Is it a good practice to use Debug.Assert and Code contract on the same method. If so what would be the order in which the code should be written?

Debug.Assert(parameter!= null); Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); 

or

Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); Debug.Assert(parameter!= null); 

Is there any rationale behind it?

like image 657
Carbine Avatar asked Dec 16 '13 04:12

Carbine


People also ask

What is the purpose of Debug assert?

Assert(Boolean, Debug+AssertInterpolatedStringHandler) Checks for a condition; if the condition is false , outputs a specified message and displays a message box that shows the call stack.

Can asserts help with debugging?

What is an Assertion? Assertions provide a useful debugging tool that allows you to document an assumption within your code and have this assumption checked automatically at run-time. Every assertion includes a predicate, or Boolean condition, that you expect will always evaluate as true.

What is assertion in contracts?

A: Contract assertions give the programmer a way to deliver precise facts to the toolchain about the expected state of a program at one point.

Does Debug assert work in Release mode?

Assert() statements (as well as other Debug class method invocations) are ignored in a Release build.


2 Answers

These are different things. A debug assert is only executed when the code is compiled as debug and therefore will only check/assert under debug. The idea is to use this for "sanity checks" for code you are developing. Code contracts can be used in either debug or release. They assure that pre and post conditions of methods comply with the expectations of the method (meet the contract). There is also a testing framework that provides similar functionality, designed for checking test compliance.

Use Debug.Assert when you want ensure that certain things are as you expect when developing the code (and in later maintenance development).

Use code contracts when you want to assure that conditions are true in both debug and release. Contracts also allow certain forms of static analysis that can be helpful in verifying that your program is "correct".

Use the Testing framework assertions when creating unit tests.

like image 182
Dweeberly Avatar answered Oct 13 '22 00:10

Dweeberly


Personally, I wouldn't use both Debug.Assert AND Code Contracts to enforce preconditions in newly written code - IMO Code Contracts supercede Debug.Assert, as they offer a more comprehensive suite of checks, not to mention the benefit which can be gained from the static checking which can be performed before the code gets to run time. Maintaining duplicate precondition checks in both the Debug.Assert and Contracts will be cumbersome.

Rationale:

  • You don't need to re-code any legacy preconditions you may have coded in Debug.Assert or throw code - you can keep the existing precondition check code and terminate it with Contract.EndContractBlock()
  • You can get the same unchecked 'release mode' behaviour when System.Diagnostics.Debug is built without /d:DEBUG if you build with contract run time checking set to None. Ref 6.2.1 in the Docs
  • Contracts allows a dev to be more expressive in code as to 'why' an invalid state has been detected - e.g. was it directly because of an out of band parameter (Contract.Requires). Otherwise Contract.Assert or Contract.Assume can check general state, and the "guaranteed correctness" of state on leaving a method can be expressed using Contract.Ensures. And Invariants express that the state must be held at all times.
  • And best of all, Static checking can enforce these Contracts as you build your code - this way you have the chance to pick up the bug through a design time or compile time warning instead of having to wait for run time. Contract Checks can be added to your Continuous Integration to look for non-compliance.

One caveat : If you are going to write Unit Tests which deliberately violate contracts, you may need to deal with ContractException - Jon Skeet explains this well here. e.g. Wire up a Contract.ContractFailed handler in your test setup to a handler which calls SetHandled and then throws a public Exception which you can catch and assert in your UT's.

like image 32
StuartLC Avatar answered Oct 12 '22 23:10

StuartLC