Customizing the behavior of System.Diagnostics.Debug.Assert [Matt Ellis]

When Inbar posted his refresher on the System.Diagnostics.Debug class, Ron Cain asked an interesting question about Assert in the context of a test harness. Because of this I thought it might be nice to expound on some of the details on exactly how Debug.Assert ends up popping up UI when a failure occurs and what you can do to change this behavior.

We’ll start by discussing what happens when a simple call like Debug.Assert(false) is made. All Debug.Assert does is check the condition and if its value is false (as it is in this case) calls Debug.Fail with String.Empty as the message. When Debug.Fail is called, we iterate over theTrace.Listeners collection and call the Fail method on each listener and then return. The subtle point here is that Debug.Assert doesn’t pop up the assertion failed dialog, but instead some listener in the Trace.Listeners collection does. The listener that does this is called the DefaultTraceListener.

As its name suggests, the DefaultTraceListener is added by default to the Trace.Listeners collection when your application runs. If you want, you can remove this listener either by calling Trace.Listeners.Remove(“Default”) at some point in your app or by using an application configuration file that removes the listener. An example configuration file would look like:

<configuration>

<system.diagnostics>

  <trace autoflush="false" indentsize="4">

    <listeners>

      <remove name="Default" />

    </listeners>

  </trace>

</system.diagnostics>

</configuration>

If you do either of these two things and then call Debug.Assert(false) your app will continue to run and you’ll have no indication that your assertion failed. If you just want to disable the UI but continue to have debugging messages written to the OutputDebugString (or to a log file if you have specified the DefaultTraceListener.LogFileName property) you can set AssertUiEnabled property on the DefaultTraceListener object to false.

Now, to answer Ron’s question on how you can get Debug.Assert() to play nice within your testing environment. The answer depends somewhat on what your hosting environment is like. If your tests simply run applications and check their return codes you could write a custom trace listener that calls System.Environment.Exit with a special error code whenever Fail is called. Perhaps instead you may choose to write a stack trace when an assert is fired to a predefined output file that your testing harness checks when it returns, if the file is empty after your test case runs then you know there were no asserts.

Hopefully this has helped to remove some of the mystery behind the Assert method on the System.Diagnostics.Debug class. If you have further questions about anything in the Diagnostics name space feel free to drop a comment and I’ll try to respond.

Cheers!