Partial Classes and Unit Tests

Published Mon, Apr 10 2006 1:53 | William

Just thought of something. A few times when I needed to create unit tests that covered private members, one thing I did was create nested classes.  I never liked this approach but in a few cases, it seemed a lot cleaner than the alternatives (after all, changing member access just to accomodate unit tests seemed equally absurd).  Anyway, I was playing around with some stuff for my book today and got to thinking about it. You can use a partial to hold your unit tests for a class. This will give you access to your private members without messing with your access modifiers.  Then, if you need to remove them before a shipment, you can do it a lot easier.  Still seems kind of klunky but ostensibly a cleaner solution than the previous way of handling it - this way your code file can hold your 'real' code and the partial file can hold the unit test stuff.  This isn't my idea, I remember reading about it a long time ago I just don't remember where I read it so I can't give the original author credit.

Anyone doing something like this?

Filed under:

Comments

# Frans Bouma said on April 10, 2006 2:24 AM:

I use reflection to retrieve the values of private variables, for example to avoid having lazy loading triggered if I want to test lazy loading ;).

However, isn't it so that unittesting is about the interface contract being obeyed by your code? So this means that internal workings can't and shouldn't be tested, as it's the interface contract that counts.

# Jake Good said on April 10, 2006 8:29 AM:

I agree with Frans... if you feel as if you need tests to test private members, the interface is bad (the private members aren't needed or aren't used properly) or the unit tests for the interface aren't covering things properly.

:: shrugs ::

# Bill said on April 11, 2006 8:36 AM:

Thanks both of you. But with Private members, what if I have really complex logic in private methods, should I be testing those, or should I just focus on the public methods?

# Scott said on April 11, 2006 5:35 PM:

Bill:

I was uncomfortable with this for a long time, but after writing a lot of unit tests I think the best bet is to test only the public interface. Use a code coverage tool if you want to ensure 100% coverage of your private methods.

# William said on April 13, 2006 8:14 AM:

Thanks Everyone - I really appreciate it!

# AndyV said on April 14, 2006 12:14 PM:

Okay, great. Both camps are well represented here. Conceptually I think everyone agrees that unit testing is to help insure that the public interface produces the same results every time. The difference in the approaches really comes down to this: the "don't touch my privates" camp is concerned primarily about whether or not the public interface fails while the "please be careful with my privates" side is concerned about WHERE something fails if it fails. I'm with Bill and Folwer in the latter camp (after all, isn't it better to have someone else handle your privates every once in a while?).

I have one concern with containing unit tests in partials: technically, you're not assuring the assemblies that you ship. I realize this will rarely happen, but what if you have a knucklehead in the organization and that person accidentally puts REQUIRED code in the partial intended only for unit tests? When you ship you've lost that functionality. Oops.

We're on a tack similar to what Franz mentions. We've used CodeDom to generate test classes. These test classes look just like the unit-to-be-tested except that the name is appended with test (e.g., Foo -> FooTest). The method signatures are exactly the same, but the methods are implemented as calls to the unit-to-be-tested methods via Reflection. We then write all the tests in the xxxTest class that is subsequently compiled into a unique assembly. This way we can write tests in the test class that access all methods, test the object that will be shipped, and avoid the possibility of including required code in test classes (sure, you could still try to put it in there but it would not support the application).

# Bill said on April 15, 2006 10:02 PM:

AndyV - drop me a line when you get a chance. I have some 2.0 Remoting code for you using Generics - I just wrote a chapter on it and would like to shoot you a copy since we talked about it before. Would like to talk about this a little more too.

Search

This Blog

Tags

Community

Archives

News

My other sites

Cool Stuff

Book Stuff

Security

ORM

Data Access

Funny Stuff

Compact Framework Stuff

Web Casts

My KnowledgeBase Articles

My MVP Profile

Design Patterns

Performance

Debugging

Remoting

My Fellow Authors

My Books

LINQ

Misc

Speech

Syndication

Email Notifications