Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am quite a beginner in code testing, and was an assert whore before. One thing worrying me in unit testing is that is often requires you to make public (or at least internal) fields that would have been private otherwise, to un-readonly them, make private methods protected virtual instead, etc...

I recently discovered that you can avoid this by using things like the PrivateObject class to acces anything in an object via reflection. But this makes your tests less maintainable (things will fail at execution rather than compile time, it'll be broken by a simple rename, it's harder to debug...). What is your opinion on this ? What are the best practices in unit testing concerning access restriction ?

edit : consider for instance that you have a class with a cache in a file on disk, and in your tests you want to write to memory instead.

share|improve this question
    
The python folks only have public. They're happy. Why worry? Why not make everything public? –  S.Lott Dec 22 '11 at 14:15
6  
Because that is far from best practices in the majority of the top languages. The real answer is to use good interfaces and such so you can use mock objects to perform testing against. –  Rig Dec 22 '11 at 14:24
    
Maybe I'm missing something, but why not write public getters for your private fields or methods? –  Gilbert Le Blanc Dec 22 '11 at 16:11
4  
"it is far from best practices in the majority of the top languages" does not logically imply (or even allude that) "Python is not a top language". –  Mike Nakis Dec 22 '11 at 16:26
1  
Precisely, it is a top language but most of the top languages are not Python and endorse setting appropriate scope. I stand by my statement. There are patterns designed to make highly testable software while ensuring variables maintain scope. Even Python programmers tend to emulate scope with prefixes from what I have seen. –  Rig Dec 22 '11 at 17:33
show 4 more comments

5 Answers 5

up vote 17 down vote accepted

You should never-ever have to

make public (or at least internal) fields that would have been private otherwise, to un-readonly them, make private methods protected virtual instead

Especially un-readonlying a field can make an immutable object mutable, and that would be a disaster.

Your tests should consider your objects as black boxes (Wikipedia), meaning that they should only be concerned with the public interface of the objects, not with details of their implementation.

If an object cannot be sufficiently tested using its public interface, then you need to find ways to provide formal and useful extensions to its interface that would facilitate testing. For example, a registration system with only a pair of Register/Deregister methods would perhaps benefit from an IsRegistered method even if it is not necessary for the application at hand; still, it is a formal and useful extension to the interface, and it will, incidentally, accommodate testing.

The important thing is that changing the implementation of the object should not require you to change the unit test. In theory you should be able to write the unit test once, and then ask multiple programmers to code multiple entirely different implementations of the object-to-be-tested to work with the unit test.

share|improve this answer
2  
Exactly! If you can't unit test it without reflection or hacks, then you've probably got a mistake in your API or your design. –  Falcon Dec 22 '11 at 17:08
add comment

In C# you can use the InternalsVisibleToAttribute to allow your test assembly to see internal classes in the assembly you're testing. It sounds like you already know this.

In most cases I'm only interested in testing the public API of my assembly. In a case where I want to do white-box testing of some unit, I move the code to an internal class, and make it a public method of that class. Then I can code a unit test for that class.

This lends itself well to dependency injection and the strategy pattern. You can abstract the method into an interface, inject the interface into your parent object's constructor, and just test that the parent delegates appropriately. Then you can test that the child object behaves appropriately. This makes everything more modular.

share|improve this answer
add comment

In my experience it is best not to expose the internals of your class specially for the test. Even though this may appear to make the test easier to write. The test is the first client of your class, so if it is hard to test your class through its public interface, it will probably be hard to use your class in other places too.

How easy the class is to test through its public API is feedback on how easy the class will be to use. Think of the tests partially as a way to prototype the usage of your class.

Try to consider why your test needs to sense something about the class that is not available through the public API. Perhaps your class is doing too much and needs to be decomposed into a group of co-operating classes instead? Then you can mock some of the collaborating classes to sense what the class under test is doing.

Try to apply the dependency inversion principal and introduce interfaces between your classes which you can mock in your tests. You can provide the collaborators to your test by using inversion of control.

Also consider applying the "tell don't ask" principal to help structure your class interface in a robust, loosely coupled, manner, where the right information is exposed and the rest is hidden.

share|improve this answer
add comment

Personally I prefer to leave the code I am testing as pure as I can and if the test code needs hacks (and in C++ nasty pointers etc) I am happy to do that.

share|improve this answer
    
    
I agree, this is the way to do it. Keep the ugliness in the test code, where it can't hurt anything. –  Alan Delimon Dec 22 '11 at 15:33
    
@AlanDelimon Might it not hurt the mind of subsequent maintenance programmers? –  flamingpenguin Dec 22 '11 at 16:36
    
@flamingpenguin ugly code can hurt programmers anywhere; but ugly test code will likely do less harm since it will only affect people modifying the class and not also people who simply consume it. –  Dan Neely Dec 22 '11 at 19:32
    
@flamingpenguin It might, but if you have to put ugly code somewhere, it might as well be in a unit test where it's less likely to need modification and be part of the application. –  Alan Delimon Dec 23 '11 at 2:02
add comment

The visibility of your code has nothing to do with your unit tests!

You make your methods private not with the purpose to hide them from testing and you don't make them public to expose for testing, right? This is your implemenation that is essential here, not the tests -- those server as proof of your code, but they are not your code.

There is a plenty of ways to enable access to hidden (private or internal) methods and properties. Many test frameworks and IDEs (for example, Visual Studio) support you here by generating everything needed for the access, you only have to author your test cases. So, why worry? Better keep your code clean and neat.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.