From: David Chelimsky Date: 2007-08-03T03:37:59+09:00 Subject: Re: Private methods not so private? On 8/2/07, dblack@rubypal.com wrote: > Hi -- > > On Thu, 2 Aug 2007, "J�rgen P. Tjern�" wrote: > > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > Daniel Berger wrote: > >> [ .. snip .. ] > >> The advantage of allowing send to access private methods is that it > >> allows you to test private methods. :) > > Isn't that a Bad Practice (tm)? Private methods are mostly meant for the > > internals of a class, and a test should really only test how the class > > interacts with the rest of the world - right? (i.e. public methods) > > No; you definitely want to test your private methods too. Conventional wisdom in the Agile/TDD community is that you shouldn't be testing private methods. The reasoning goes something like this: 1. If you're doing TDD, you're sending messages to objects that other objects in your system will send. The corresponding methods should be public. 2. In TDD, private methods appear through refactoring, and therefore are already tested implicitly through the tests of public methods. 3. When you feel the need to add tests on private methods (which have appeared through refactoring), it should be considered a sign that a new object is wanting to be born and should be extracted out into a new class. My sense is that some of this thinking is a product of the fact that testing privates in Java means using reflection, resulting in refactoring inefficiencies. In Ruby, testing privates is fairly easy and we don't really have the refactoring tools that the Java community has, so refactoring in Ruby tends to be much more manual anyhow. That said, I think the OO design questions that get raised are worthy of exploration when you feel the need to test something private. WDYT? > First of > all, if you're writing a class, you need to test its internals; > nothing should be a "black box" for the tests. Second, private > methods are actually available to the world, even without send. They > just have to be called the right way: > > puts "Hi" > class C > attr_accessor :x > end > C.class_eval { define_method "y" } > > puts, attr_accessor, and define_method are all private, but you'd > certainly want to test them if you had written them. > > > David > > -- > * Books: > RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242) > RUBY FOR RAILS (http://www.manning.com/black) > * Ruby/Rails training > & consulting: Ruby Power and Light, LLC (http://www.rubypal.com) >