Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit tests in same class (with conditional compilation)?

I'm aware of (and agree with) the usual arguments for placing unit tests in a separate assembly. However, of late I've been experiencing some situations where I really want to be testing private methods. The behind-the-scenes logic in question is complex enough that testing the public and internal interfaces doesn't quite get the job done. The testing against the class's public interface feels overwrought, and I see several spots where a few tests against privates would get the job done more simply and effectively.

In the past I've tackled these kinds of situations by making the stuff I need to test protected, and creating a subclass that I can use to get at it in the test framework. But that doesn't work so well on classes that should be sealed. Not to mention bloating the test framework with all that scaffolding.

So I'm thinking of doing this instead: Place some tests in the class, where they can get at the private members. But keep them out of the production code using '#if DEBUG`.

Does this seem like a good idea?

like image 984
Sean U Avatar asked Jun 14 '12 15:06

Sean U


People also ask

Can we use if condition in unit testing?

Yes - they will both fail under the same conditions. But putting the parameters in the wrong order will give a very misleading message.

Should unit tests be in the same package?

Unit tests can be in any package. In essence they are just separate classes used to test the behaviour of the class being tested.

Are unit tests run in parallel?

By default, unittest-parallel runs unit tests on all CPU cores available. To run your unit tests with coverage, add either the "--coverage" option (for line coverage) or the "--coverage-branch" for line and branch coverage.

Can unit tests depend on each other?

Tests should never depend on each other. If your tests have to be run in a specific order, then you need to change your tests. Instead, you should make proper use of the Setup and TearDown features of your unit-testing framework to ensure each test is ready to run individually.


1 Answers

Before anybody asks...

The solution to OP's problem is to properly incorporate IoC with DI and eliminate the need of testing private method altogether (as Joel Martinez noted). As it's been mentioned multiple times, unit testing private members is not the way to go.

However, sometimes you just can't change the code (legacy systems, risk of breaking changes - you name it) nor you can use tools that allow private members testing (like Typemock, which is paid product). For such cases, you can either not test at all, or cut corners. Which I believe is situation OP's facing.


Leaving private methods testing discussion aside...

Remember you can use reflection to access and invoke private members.

In my opinion, placing conditional debugs in the class itself is rather bad idea - it adds noise (as in, something unrelated) to the class code. Sure, it will be gone in release, but you (and possibly other programmers) will have to deal with it on the daily basics.

I realize your idea might sound good on paper - simple test wrapped with conditional debug. But in reality, tests quickly turn out to use extra variables (those will also have to be placed in the class code), some utility (extra references, custom types), testing frameworks (even more references) and what not. This all will have to be somehow connected to the class code. Put that all together, and you quickly end up with an unmaintanable monster.

Are you sure you want to deal with that? Especially considering that throwing together simple reflection-based utility is probably not that hard.

like image 136
k.m Avatar answered Sep 29 '22 09:09

k.m