27

I recently came across some newly written code that was interspersed with lots of Debug.Assert (C#).

Should we still use this widely despite the usage of TDD, BDD and Unit Testing in general?

2
  • 10
    I can't see how one excludes the other.
    – superM
    Jan 10, 2013 at 8:07
  • 2
    @superM I've definitely seen lazy developers add tests as asserts before as they had writen their code such that it was hard to mock out dependencies. needless to say I wouldn't recommend this
    – jk.
    Jan 10, 2013 at 8:42

3 Answers 3

27

I don't see any reason why you shouldn't use Assert. By doing so you've already acknowledged a need for guards, like preconditions & invariants, and are making a move towards Design by Contract. Assert is only one way of achieving this...

// Precondition using Asert
void SomeMethod(Foo someParameter)
{
    Debug.Assert(someParameter != null)
}

// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
    if (someParameter == null)
        throw new ArgumentNullException("someParameter");
}

// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
    Contract.Requires(someParameter != null);
}

// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
    Require.ArgumentNotNull(() => someParameter);
}

All are ways of achieving the same thing: robustness in code. It just comes down to choosing an option, of which Assert is a valid choice.

Note that I have not mentioned unit tests at all so far, as they accomplish something very different. A unit test formally proves the robustness of the code by exercising a guard:

[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
    delegate call = () => someObject.SomeMethod(null);

    Assert.That(call).Throws<ArgumentNullException>();
}

This is an entirely different kind of assert...

**Note that in some frameworks it's actually quite difficult to unit test for an assertion failure, as an assertion failure can bring down the entire runtime, so one of the other options might be preferred...*

11

I consider asserts and unit tests to be two different tools in my toolbox. Some things are better suited to one, and some are better suited to the other.

As an example, these days I mostly make use of asserts to validate parameters for non-public methods.

7

I view Debug.Assert as premature optimization nowadays. Unless you really need the performance, suppressing the Assert in release mode can hide bugs for longer.

As MattDavey points out code contracts can be a superior, providing static checking instead of dynamic checking, and if not available I'd prefer Trace.Assert or a plain old if(x) throw SomeException;

4
  • 4
    It is worth to mention that generating code with Visual Studio in release mode will cause all calls to methods of the Debug class to be skipped from compilation... so suppressing calls to Assert simply for performance is not just premature optimization, it is a plain nonsense.
    – Konamiman
    Jan 10, 2013 at 12:47
  • @Konamiman that's the point, I almost always want it to fail in the same way in release mode :. Debug.Assert is of no use to me 97% of the time
    – jk.
    Jan 10, 2013 at 12:50
  • What's that 3% then, @jk? Only legacy code, or some other instance?
    – DougM
    Feb 28, 2014 at 14:08
  • 1
    @DougM performance critical code, its a reference to the knuth quote. I'd also add that I think the heartbleed bug demonstrates that my view is the correct one, unless you have no other choice, do not elide precondition checks in your release code
    – jk.
    Apr 17, 2014 at 12:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.