unit-testing.net-4.0code-contractsmicrosoft-contracts

.NET 4.0 code contracts - How will they affect unit testing?


For example this article introduces them.

What is the benefit?

Static analysis seems cool but at the same time it would prevent the ability to pass null as a parameter in unit test. (if you followed the example in the article that is)

While on the topic of unit testing - given how things are now surely there is no point for code contracts if you already practice automated testing?

Update

Having played with Code Contracts I'm a little disappointed. For example, based on the code in the accepted answer:

public double CalculateTotal(Order order)
{
    Contract.Requires(order != null);
    Contract.Ensures(Contract.Result<double>() >= 0);
    return 2.0;
}

For unit testing, you still have to write tests to ensure that null cannot be passed, and the result is greater than or equal to zero if the contracts are business logic. In other words, if I was to remove the first contract, no tests would break, unless I had specifically had a test for this feature. This is based on not using the static analysis built into the better (ultimate etc...) editions of Visual Studio however.

Essentially they all boil down to an alternate way of writing traditional if statements. My experience actually using TDD, with Code Contracts shows why, and how I went about it.


Solution

  • I don't think unit testing and contracts interfere with each other that much, and if anything contracts should help unit testing since it removes the need to add tedious repetitive tests for invalid arguments. Contracts specify the minimum you can expect from the function, whereas unit tests attempt to validate the actual behaviour for a particular set of inputs. Consider this contrived example:

    
    public class Order
    {
        public IEnumerable Items { get; }
    }
    
    public class OrderCalculator
    {
        public double CalculateTotal(Order order)
        {
            Contract.Requires(order != null);
            Contract.Ensures(Contract.Result<double>() >= 0);
    
            return 2.0;
        }
    }
    

    Clearly the code satisfies the contract, but you'd still need unit testing to validate it actually behaves as you'd expect.