Is conditional compilation a valid layout / stub strategy for unit testing?

In a recent stubbing question, many answers suggested C # interfaces or delegates to implement stubs, but one answer suggested using conditional compilation while maintaining static binding in production code.This answer was changed to -2 while reading, so at least 2 people actually considered That is the wrong answer. Perhaps the misuse of DEBUG was the cause, or perhaps the use of a fixed cost instead of a broader review. But I cannot help but wonder:

Is using conditional compilation an unacceptable method for implementing unit test stubs? Sometimes? Always?

Thanks.

Edit-add: I would like to add an example as an experimental experiment:

class Foo { public Foo() { .. } private DateTime Now { get { #if UNITTEST_Foo return Stub_DateTime.Now; #else return DateTime.Now; #endif } } // .. rest of Foo members } 

compared with

 interface IDateTimeStrategy { DateTime Now { get; } } class ProductionDateTimeStrategy : IDateTimeStrategy { public DateTime Now { get { return DateTime.Now; } } } class Foo { public Foo() : Foo(new ProductionDateTimeStrategy()) {} public Foo(IDateTimeStrategy s) { datetimeStrategy = s; .. } private IDateTime_Strategy datetimeStrategy; private DateTime Now { get { return datetimeStrategy.Now; } } } 

This allows you to disable the outbound dependency on "DateTime.Now" through the C # interface. However, we added a dynamic dispatch call, where static would be sufficient, the object is larger even in the production version, and we added a new failure path for the Foo constructor (selection may fail).

Am I not worried about anything here? Thanks for the feedback!

+4
source share
6 answers

Try to keep the production code separate from the test code. Maintain different folder hierarchies. Various solutions / projects.

If not , you are in the world of legacy C ++ code. Nothing happens here. If conditional blocks help you get some of the code to be tested, and you will see an advantage. By all means do it. But try not to let this get any dirtier than the initial state. Clearly comment and delimit conditional blocks. Proceed with caution. This is an effective method of obtaining outdated code under a test harness.

+3
source

I think this reduces clarity for people viewing code. You do not need to remember that to understand the context, there is a conditional tag around certain code.

+2
source

No, this is terrible. It seeps into your production code (even if it is disabled)

Bad bad.

+1
source

The test code should be obvious and not mixed in the same blocks as the tested code.

This is almost the same reason you shouldn't write

 if (globals.isTest) 
+1
source

I thought of another reason, it was terrible:

Many times you cheat / drown something, you want its methods to return different results depending on what you are testing. This either eliminates this, or makes it uncomfortable, like all hell.

+1
source

This can be useful as a tool you can rely on, since you refactor testability in a large code base. I can see how you can use such methods to provide smaller changes and avoid the big bang refactoring. However, I would worry that I would describe such a technique too much and try to ensure that such tricks do not live in the code base for too long, otherwise you risk making the application code very complicated and difficult to follow.

0
source

Source: https://habr.com/ru/post/1276893/


All Articles