LJM
LJM

Reputation: 6454

Is it ok to use #if debug directive in C#?

We have a class a class that looks something like the following:

public class Processor
{
    //set timeout in seconds
    private const int TIMEOUT = 600;

    public void Process()
    {
        //DO SOMETHING HERE

        //CHECK TO SEE IF TIMEOUT HAS BEEN HIT
    }
}

Essentially, we'd like to write a unit test to see if a timeout is experienced after the specified amount of time. Obviously, we don't want to have to wait 10 minutes each time we run tests. With this in mind, my question is:

How can we manage this value so that it could be, perhaps, 10 seconds during testing but 10 minutes in production? There are many obvious ways to do this, but I'm trying to determine what the cleanest way would be. Should we expose this as a property? Include it as a constructor parameter? Include it as a method parameter? Use compiler directives?

Upvotes: 2

Views: 2923

Answers (4)

Vadim
Vadim

Reputation: 21714

I would mock that code checks for a timeout.

If you something similar to this code:

public class Processor
{
    //set timeout in seconds
    private const int TIMEOUT = 600;

    public void Process(ITimeout timeout)
    {
        //DO SOMETHING HERE

        timeout.CheckTimeout(TIMEOUT);
    }
}

public interface ITimeout
{
    bool CheckTimeout(int timeout);
}

You can mock CheckTimeout method.

You can create a mock class like this one:

public class TimeoutMock : ITimeout
{
    public bool TimeoutExpired;

    public bool CheckTimeout(int timeout)
    {
        return TimeoutExpired;
    }
}

And you test would look something like this:

[TestMethod]
public void TimeoutExpires()
{
    var processor = new Processor();
    var mock = new TimeoutMock();
    mock.TimeoutExpired = true;
    processor.Process(mock);
}

Upvotes: 3

Mitch Wheat
Mitch Wheat

Reputation: 300729

Including it as a constructor parameter would be my preference.

The problem with #if debug directives is they are too easy to break if the right symbol is not defined. Plus they are usually used to exclude code from Release (or include code in Debug); It makes testing harder and I've seen them result in subtle errors where code with a side-effect was called in Debug but not in Release (but not recently).

Upvotes: 0

Nick Bedford
Nick Bedford

Reputation: 4445

#if DEBUG
const int TIMEOUT = 60;
#else
const int TIMEOUT = 600;
#endif

I don't think this would be a big problem. Somewhere along the line you're going to have to use the preprocessor unless you have some other way of defining build target at runtime.

Upvotes: 0

Noon Silk
Noon Silk

Reputation: 55152

For your exact scenario, I'd probably have a appSettings variable that determines the timeout for the appropriate server (dev/whatever).

In general though, it is quite appropriate to use the #if DEBUG directive at appropriate times. But in general, you'll only use that when you actually want to prevent compilation of the given code inside it, in release mode.

A classic reason to use such a directive, at least from when I've found, is to stop logging statements being included at all, in release code. Another is when you may include a certain general library in all projects, but certain code in it is not relevant for a given platform you are deploying to (i.e. Compact Framework doesn't have X class, so you use the directive to determine CF mode, and write code accordingly).

Upvotes: 8

Related Questions