Thibaut Van Spaandonck’s blog
Some stuff about Web and .NET development
-
Dino Esposito @ Visug : C# 4.0 & testability
Posted on October 17th, 2009 1 commentThis last 8th of October, Dino Esposito, a very well known figure in the .NET world, came to the Visug to talk about C# 4.0 and testability. Here’s a summary about the session :
Software testability
Code should ideally guarantee :
- Visibility of the current state
- Control degree at which code allows to send input data for testing purposes
- Simplicity of the code results in more reliable test results
Introducing the .NET 4.0 code contracts API
The ecosystem at a glance
- Code contracts library
- Rewriter
- Static checker
- Contract reference generator
1. Code contracts API
3 basic types of contracts :
- Preconditions
- Postconditions
- Invariants
Exposed via the contracts class (System.Diagnostics.Contracts)
2. Rewriter
- Translates contracts into code
- Modifies MSIL instructions to place contracts checks where they logically belong
- Executable is ccrewriter.exe
3. Static checker
- Examines code without executing it and tries to prove that all the contracts are satisfied
- Lists unproven contracts to fix, otherwise you should debug or cover it with unit tests
- Detects if there’s a possibility of contract violation
4. Assembly reference generation
- Extracts contract information from source code and returns an assembly with contract-only information
- Used by rewriter & static checker
- Executable is ccrefgen.exe
Steps of a method
- Check validity of parameters & stats
- Do real work
- Check of existing works
- Update state accordingly
Set up
- Add reference to mscorlib
- Contract must be specified in the body of the methods
- Contracts are not mandatory. You can do without
Preconditions, postconditions and invariants
Preconditions
- Requires(bool condition)
- Requires<TException>(bool condition) throws an exception if condition is not met
- if-then-throw statements
- RequiresAlways(bool condition) is like Requires but stripped off in retail builds
Postconditions
- Ensures(bool condition), condition must be true at the end of the method
- EnsuresOnThrow<TException>(bool condition), condition must be true if exception is thrown. Allows for checks even if exceptional return arises (network error, stack overflow, …)
- Helper methods
- Result<T>()
- OldValue<T>(T variable)
- ValueAtReturn<T>(out T variable)
Invariants
- Invariant(bool condition), object-wide condition that must hold for the lifetime of the class
- All invariants for a class are defined in one place
Best practice :
- Define invariants before implementing the class
- Express the conditions under which the object is in good state
- Could be hard to add them at a later time
Assert & assume
- At runtime, fully equivalent to Debug.Assert
- Static checker attemps to prove any Assert, emitting a warning if it fails
- Static checker treats Assume as always true, adds the assumption to its collection of facts
Quantifiers
- Used to iterate a check on all elements of a list
- ForAll(…), true if condition is met by all elements
- Exists(…)
Interface contracts
- Define a separate class for the contract because we can’t add code to interface memebers (no mixins in C#)
- Link to the interface via attribute
Contracts & inheritance
Contracts are inherited by derived classes, regardless wether you invoke base class methods in overrides
Code contracts & debugging
- When failure, contract raises
- ContractFailedException
- ContractFailedEventArgs
- No default handler (thrown everytime)
- Register handler to ContractFailedException at startup (Global.asax for ASP.NET, Main method for WinForms)
Contract failures & unit tests
- You don’t want contract exceptions in unit tests
- Rather want exceptions to be reported as tests failures
- SetHandled() to let assume exception has been handled and SetUnwind() to clear the stack
Summary
- Code contracts as part of the design effort
- Adds testability to classes & code
- New API coming up in C# 4.0
And one final important quote of Dino Esposito :
“Testable code means that it exposes every significant part of it in order to check its correct behaviour”See you next time



