Geeks With Blogs
Mark Pearl

 

I have recently being trying to implement TDD as a practice in writing code. Up to now I buy into many of the benefits of TDD but it is one thing agreeing that a practice is good and a totally different thing implementing the practice.

The approach I have taken was relatively simple,

  • Write a test to exercise the functionality you want in a method
  • Run test – it will fail
  • Implement method
  • Run test – it should pass
  • Repeat first step

Seems simple enough…  when it came to implementing the process a concern arose. I had written some tests for methods that ultimately I did not want to be publicly exposed. Most of the literature I have read up to now says you should only be testing public methods for unit tests – but during the development process I found these methods fairly tricky to write and so writing tests for them had helped in the development process. Now that I had made the methods private it seemed a step backward to delete the tests. With this concern in mind I emailed one of my friends who has more experience with TDD and this was his response…

My feeling is that as long as you are following SRP at a class level, test what is public. If your class has multiple responsibilities, then only testing public functions is going to leave things untested.

 

There is the option of marking methods an internal, then using the InternalsVisibleTo attribute in your AssemblyConfig to expose your internal methods to your test assembly. This is one option, but if  you are doing the SRP thing, then you probably don’t need it.

 

With your example, I would see the fact that you are trying to test some private methods as a potential code smell – could things be split into smaller classes? Of course sometimes the tests add no value on their own and do get thrown away as a normal course of doing TDD.

 

Even before I had received his response I had made an attempt to refactor my code and realized that the methods that I was testing privately would be better suited to being handled in a separate class. After moving this methods I was much happier with the structure of the classes and I found some reuse benefits – this just validated the fact that in this instance the tests for private methods were a code smell that I had broken the SRP.

Does anyone have additional/alternative views?

Posted on Tuesday, November 1, 2011 9:47 AM Misc | Back to top


Comments on this post: Attempts at TDD–Testing Private Methods

# re: Attempts at TDD–Testing Private Methods
Requesting Gravatar...
Hi Mark,

"Testing non-public members" is not necessarily a code smell. If you have a lot of internal, non-public functionality in a class, then it is wise in my eyes to cover this with dedicated tests. TDD is not about visibility in the first place, but about functionality.

(And apart from that: If you've refactored some functionality into separate (helper-) classes, these classes shouldn't be made public in most cases. Because you would then make functionality public which was encapsulated before. THIS would be a smell...)

I blogged about this exact issue here on geekswithblogs:
http://geekswithblogs.net/thomasweller/archive/2011/10/31/some-myths-of-textbook-tdd-and-why-they-are-wrong.aspx (see the '#2' section).

Regards
Thomas
Left by Thomas Weller on Nov 01, 2011 2:13 PM

# re: Attempts at TDD–Testing Private Methods
Requesting Gravatar...
Remember that TDD doesn't mean you have to test absolutely everything either. The tests are driving your development but it doesn't mean every single line needs to be covered by tests - that's a different beast entirely.

If development suffers because we're too busy changing our API so that it can be tested without worrying about access modifiers, we're probably injecting test-smell rather than code-smell.

Be practical about TDD, that is after all one of the tenets of agile!
Left by WilliamBZA on Nov 02, 2011 7:14 AM

# re: Attempts at TDD–Testing Private Methods
Requesting Gravatar...
Of course, you can overdo everything.

I'm just not willing to buy in the fact that I'm not allowed to write a test for something only because I'm not exposing it directly to the outside world via 'public'. IMHO, this takes an eventually valuable option from the table - without any concrete necessity.
Left by Thomas Weller on Nov 02, 2011 12:16 PM

Your comment:
 (will show your gravatar)


Copyright © MarkPearl | Powered by: GeeksWithBlogs.net