5

So I'm looking for some advice on how test a class I've written.

It intentionally consists of one public method Run() which accepts varaibles and sets of a long running process. This method consists of numerous calls to private methods that perform specific tasks but shouldn't be public accessible.

My query is, in this case, it seems logical to unit tests all of my private methods. However lots of people suggest that testing private methods is a bad practice.

So my question is should I just go ahead and test the private methods or has anybody been in a similar situation and can suggest an alternative method? There is absolutely no way I can reliably test all of my private methods through the one public method.

Any help appreciated and apologies if my question isn't the clearest. The application is written in C# if thats of any help.

Thanks

mat-mcloughlin
  • 6,492
  • 12
  • 45
  • 62
  • 1
    Hi, see this answer for why you shouldnt test private methods and also how to test them: http://stackoverflow.com/questions/250692/how-do-you-unit-test-private-methods – Nobody Dec 07 '10 at 12:00
  • thanks rmx, I know how to test private methods and I know all about the "brittleness" of doing so, but a useful link to a latecomer to the question. – mat-mcloughlin Dec 07 '10 at 12:02

3 Answers3

6

Personally I take a pragmatic point of view for this sort of thing - that it's okay to make unit tests "white box" tests (i.e. you can take implementation details into account and test them) but don't go so far down that route that they end up being hugely brittle.

I'd make the private methods internal and test them via InternalsVisibleTo. Also run some "black box" tests via just the Run method... it sounds like these are really integration tests more than unit tests.

Another thing to consider is whether this really should be one class. Are the tasks separable? Would they make sense as individual classes themselves, with the current class just coordinating them?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I see. Testing private methods is rather bad practice, since they're implementation details? Live and learn :) – Matthias Meid Dec 07 '10 at 12:03
  • That was my thinking if I was going to test them this way, can't be bothered faffing around, internal would do. – mat-mcloughlin Dec 07 '10 at 12:04
  • @Mudu I get that testing private methods is bad practice. Its just in this case it seems logical. I just thought I'd question the community to make sure I'm not being daffed – mat-mcloughlin Dec 07 '10 at 12:05
  • 1
    Looka like you win again Skeet! – mat-mcloughlin Dec 07 '10 at 12:30
  • Plus one from me.. i get grief from TDD purists who think you shouldn't test private methods. If it's code, test it. Private/public is for usage, not code testing. – Quango Jan 21 '13 at 17:30
0

Why is testing private methods bad practice? I do, using the Accessors generated by Visual Studio Test Suite. You might mock objects your class depends on to figure out what methods are invoked on them, but I suppose this does not help you really figuring out what happens inside your class, does it?

Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
0

Since you already have a written application, Pex might be the best choice. It will seek out all combinations of input until it determines that it has sufficiently covered all code paths.

This will allow you to test entirely through the public API, while still ensuring high code coverage.

Next time, though, write the tests first. It will give you a better design.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • I get TDD Mark, but in this case when I intentionally have only one public method I'm not sure how TDD would have helped. The intention was always to hide all the logic – mat-mcloughlin Dec 07 '10 at 12:08
  • That's not TDD then. In TDD, the tests *drive* the design. That's not what you did. It sounds like you had it all figured out on beforehand. – Mark Seemann Dec 07 '10 at 13:59
  • 1
    Mark, it sounds like you recommend making methods public for testing purposes, even if they are not needed for any other reason. That is, the methods will not be called other than by the tests, and not by any production code. This sounds to me like you get a more complicated public interface purely for extra testability. Why is this better than Jon Skeet's suggestion of using InternalsVisibleTo and keeping the public interface clean? – Simon D Jan 24 '11 at 12:43
  • Because it will lead to a better and more flexible API. I never said you had to add more *methods*. It would be much better to add more *classes*. A single big class with one entry point is a guaranteed SOLID violation. It's not object-oriented code - at best it's a Transaction Script. – Mark Seemann Jan 24 '11 at 13:36
  • 1
    OK but more classes is going to give you a bigger public interface, just as much as more methods, unless all those classes are private. A linker provides a very simple interface (essentially: pass a number of objects, get an executable out), which masks a lot of complexity. In that case wouldn't you want to test in more depth than just the public interface? Surely it shouldn't provide a public method to relocate an object to a particular base address (say), even though you might want to test that functionality. – Simon D Jan 24 '11 at 14:04
  • You can't have more flexibility without a bigger public interface. – Mark Seemann Jan 24 '11 at 15:36