Asserts are NOT evil

I have been asking this question to many developers after having heard  the viewpoints of many others on the alt.net list. The common view point seems to be that Debug.Assert is evil and shows a unit test that is missing. Many also made comments such as that if I am using a Debug.Assert that I should have immediately after it matching production behaviour. Some quotes from the discussions I have had:

Asserts are evil, you should write a unit test to show the failure

Asserts are antiquated

Asserts used to be useful in the C/C++ days because you would be testing conditions that should never be false but could be because of direct memory manipulation etc they have no real use in a managed environment.

I think that all of these viewpoints have really missed the point of why I would want to use an Assert. To me the main reason to Assert is that:

 I want this case tested when in Debug mode but I don’t actually WANT to run the test in production. If the test were to fail in production then let it fail or let it return incorrect information

At the outset this may sound like TDD sacrilege perhaps going through an example will clear it up. Let’s say that for whatever reason I am re-implementing Array.BinarySearch. One of the conditions of BinarySearch is that the thing I am searching is sorted. This is a canonical example of where I would want to use an Assert. Writing a unit test for this condition (or expecting a runtime failure from it) is ridiculous as it would be take a O(log n) operation and make it O(n + log n). In other words it would take me longer to insure that the thing is actually sorted than it would take me to actually search it.

 

Spec# currently also does not support this type of scenario. TO support it I would need the ability to say this condition only applies to the prover, do not emit runtime code for this. Hopefully this is something that will be added in the near future.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

13 Responses to Asserts are NOT evil

  1. Adam D says:

    Hangovers are evil.

  2. JD Conley says:

    I know this is a very specific reason to use Debug.Assert(), but in ASP.NET hosted applications I like to throw one on the un-handled global exception event handlers you can setup. That way while running a debug build on my workstation I get an assertion. Of course, these handlers are also logging and redirecting to friendly error pages and such.

  3. The_Tzar says:

    Assertions are indeed handy when you want to be fault restrictive in development-mode and fault-tolerant in production-mode. I do log failures though.
    Currently I’m writing something that has to go through binary data. Under development I want to know when some unexpected comes along, in production you wouldn’t hardly notice in most cases if some incoming data was interpred incorrectly.

  4. @David: exactly my philosophy. Unit tests cover my public APIs. Assertions ensure my private APIs are being called with correct parameters, consistent state etc. My unit tests probably will catch any issues, but the mere fact that Debug calls are optimized out of Release builds means it’s win / win.

  5. Colin Jack says:

    @David
    That doesn’t seem wrong to me. Thinking back when I’ve written reasonably complex classes I have found issues using Asserts in private methods, things that the (exception raising) preconditions on the public methods and the unit tests had missed. So yeah it can be useful, though I guess it depends on the complexity of the issue.

  6. Colin Jack says:

    I used to use Debug.Assert a lot but these days I just throw exceptions when preconditions are violated, I haven’t found any situations where I haven’t wanted the test to run in production but that seems like a situation where using Debug.Assert is still useful.

  7. David Fauber says:

    My general pattern has been asserts for private methods, unit tests for public. Is this wrong?

  8. Greg says:

    Steven:

    The classic case is something like the binarysearch I mention above. Insuring the pre-condition costs more than the operation itself which in something like a binarysearch is pretty important. In production code if you give me an array thats not sorted and ask me to binary search it I will try my best….

    In debug I will try to insure that you never give me bad data and the assert will alert you to the case that you are.

  9. FOR says:

    Interesting.. I’ve been debating the issue of the Debug.Assert statements with colleagues lately. We’re actually using TDD while writing a new (large) application. I don’t think Debug.Assert statements are evil, so I quite agree with your bottom line. However, my justification is different:

    I want to tell the developers when they’re not respecting some pre-condition to this piece of code. That’s why I want a Debug.Assert statement here.

    It happens to me every day. I’m writing a piece of code to make some acceptance test and unit test go green. Let’s say that the code retrieves an instance of some domain object that, in all cases considered by the acceptance tests, is guaranteed to exist. Then, the code needs to check a property on that instance. As I write the code, because I am paranoid, I instinctively wonder what to do if the instance is null (because calling a method or property on a null reference would bomb).
    Usually, I’d write a unit test showing the behavior of that method when the instance is null, but I have no acceptance test triggering that, and -for the sake of argument- let’s say that, it is really impossible for that to happen when we consider the application as a whole. Heck, I could use predicate calculus to prove it to you: that instance will never be null under all circumstances in which (at this point in time) that method can be called. So we can’t quite write a meaningful acceptance test to trigger that null condition. Therefore we shouldn’t need to write the code for it, nor a unit test for it.
    That’s when I like to put a Debug.Assert statement.

    If, later on, a colleague calls that method under different conditions that, suddenly, make it possible for that null condition to happen, they’d get the error message from my Debug.Assert statement (e.g.: such and such instance was unexpectedly null), and they’d be able to figure out what’s going on without having to debug and trace.

  10. Steven says:

    I hardly use Debug.Asserts these days. I rather throw a descent Exception. Last few months I even switched to throwing EnsuresViolationExceptions (I borrowed the concept from Spec#) when my code fails to deliver it’s post condition.

    Can you explain in what situations you use asserts instead of throws?

  11. Greg says:

    Fair enough Jeremy.

    I am curious though .. what would your unit tests for BinarySearch look like? :)

  12. Two words: “Legacy Code.” The only time I’ve used Debug.Assert is with legacy code with zero tests.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>