Spec-ing private methods?

hello there,
how do you tipically spec private methods? The thing is Ï have something
like this:

def some_method
complex_method + other_complex_methods
end

private
def complex_method…
def other_complex_methods …

and the two complex methods can get really tricky to get right, I would
like
to be able to write specs for them, how do you do that? I mean I cannot
do:

object.some_private_method

am I?

thanks in advance,
joaquin

On Oct 14, 2009, at 3:36 PM, Joaquin Rivera P. wrote:

def other_complex_methods …

and the two complex methods can get really tricky to get right, I
would like to be able to write specs for them, how do you do that? I
mean I cannot do:

object.some_private_method

You have a few options:

  1. Make the method public in the object you are testing
  2. Make the method public in the test case
  3. Don’t test the method
  4. Use send or (send) to call it.
  5. Refactor private methods to a new object, and make the methods
    public in that object.

Most of those options suck (esp. 1, 2, 3, & 4) - usually it represents
a design flaw (you are doing too much in your class).

Scott

On Wed, Oct 14, 2009 at 5:49 PM, Scott T. [email protected]
wrote:

  1. Make the method public in the object you are testing
  2. Make the method public in the test case
  3. Don’t test the method
  4. Use send or (send) to call it.
  5. Refactor private methods to a new object, and make the methods public in
    that object.
    Most of those options suck (esp. 1, 2, 3, & 4) - usually it represents a
    design flaw (you are doing too much in your class).
    Scott

3 is ok.

A “private” method just means it’s an implementation detail that is
outside of your API. If you are aiming to test the behavior of your
API, then you don’t care about implementation details.

-foca

On Wed, Oct 14, 2009 at 3:49 PM, Scott T. [email protected]
wrote:

Most of those options suck (esp. 1, 2, 3, & 4) - usually it represents a
design flaw (you are doing too much in your class).

I disagree that the simple existence of private methods is a sign of a
design flaw. There are plenty of use cases for which private methods
are the simplest and most practical approach. I use them all the time
to help me deconstruct complicated multi-step actions into shorter,
more atomic chunks of logic. They’re also how callbacks and filters
are usually implemented in Rails.

That said, though: I usually don’t bother testing them. I use RSpec
for unit testing, and when I’m doing that I care about the external
behavior
of the unit. I want to know what the object will do when I
poke it from another object. Private methods are an implementation
detail, not a “What does it do?” but rather “How does it do that?” –
and that’s not any other class’s business.

They’re also not usually that complex or brittle. I’ll know they work
because the public or protected methods that call them work; and I
don’t need tests to understand them. In the exceptional cases where
they might be complex (e.g., some ActiveRecord callbacks or
authentication filters) you’re right – putting them into a module and
testing that module makes sense.


Have Fun,
Steve E. ([email protected])
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org

On Oct 14, 2009, at 4:24 PM, Nicolás Sanguinetti wrote:

def some_method
cannot do:
that object.
Most of those options suck (esp. 1, 2, 3, & 4) - usually it
represents a
design flaw (you are doing too much in your class).
Scott

3 is ok.

Yeah, 3 is OK, although ideally you are testing the method, albeit
indirectly through the public interface.

Scott

On 14 Oct 2009, at 20:49, Scott T. wrote:

object.some_private_method
Most of those options suck (esp. 1, 2, 3, & 4) - usually it
represents a design flaw (you are doing too much in your class).

I’m with Scott, this usually indicates a design flaw, and 5 is usually
the solution. The clue is in the names you gave them - you shouldn’t
have complex methods, especially private ones.

Can you post any of the code so we can see where the complexity/
problem is?

Ashley


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

hello

2009/10/14 Ashley M. [email protected]

do:

  1. Refactor private methods to a new object, and make the methods public
    Can you post any of the code so we can see where the complexity/problem is?

hey ashley,
the code itself is not very interesting, it’s some fast hacking I’m
doing
dumping chess positions into a string, and then the methods given the
character index on that string should translate it to two-dimensional
vectors in the board, boring: mainly math calculations multiplying
columns
by some number and adding row numbers and such, and during the spec-ing
of
the public method the question arose…

and yeah, I think 5 it my favorite at the moment, they don’t have to be
private anyway, also IMHO testing private methods through the public API
it’s not in general applicable (only thinking here, no code sample)…

but anyway I wanted to hear what you guys think about it

thanks,
joaquin

On 14 Oct 2009, at 21:31, Stephen E. wrote:

I disagree that the simple existence of private methods is a sign of a
design flaw. There are plenty of use cases for which private methods
are the simplest and most practical approach. I use them all the time
to help me deconstruct complicated multi-step actions into shorter,
more atomic chunks of logic.

They’re also not usually that complex or brittle.

I don’t think Scott meant to imply that private methods are bad, only
that complex ones private methods are. I use private methods for the
same reason you describe above, to break complex actions down into
more understandable chunks. When it takes 30 private methods before I
can understand the code, that usually indicates there’s a problem, and
that a new class needs to emerge. (There are usually other signs of
this too, though.)

Ashley


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

On 14 Oct 2009, at 22:33, Matt W. wrote:

Yup. Sprout class[1] works for me, every single time.

[1]http://xunitpatterns.com/Sprout%20Class.html

By the way, Sprout Class comes from ‘Working Effectively with Legacy
Code’ (Feathers), which is probably the best book I’ve read on TDD
(Admittedly I’ve yet to read The RSpec Book). Highly recommended.

cheers,
Matt

+447974 430184
[email protected]
http://mattwynne.net

cheers,
Matt

+447974 430184
[email protected]
http://mattwynne.net

On 14 Oct 2009, at 20:49, Scott T. wrote:

  1. Don’t test the method
  2. Use send or (send) to call it.
  3. Refactor private methods to a new object, and make the methods
    public in that object.

Most of those options suck (esp. 1, 2, 3, & 4) - usually it
represents a design flaw (you are doing too much in your class).

Yup. Sprout class[1] works for me, every single time.

[1]http://xunitpatterns.com/Sprout%20Class.html

cheers,
Matt

+447974 430184
[email protected]
http://mattwynne.net

On 14 Oct 2009, at 22:48, Matt W. wrote:

By the way, Sprout Class comes from ‘Working Effectively with Legacy
Code’ (Feathers), which is probably the best book I’ve read on TDD
(Admittedly I’ve yet to read The RSpec Book). Highly recommended.

I’ve heard good things about this book too. Do you also recommend
xUnit Patterns?

Bizarrely, I’m including xUnit patterns as a reference in a
presentation on mocks I’m giving tomorrow[1], despite never having
read it. (Only because I know it contains some mocking definitions I
refer to…)

Incidentally, the mocking section of the RSpec Book is very good.
Which is to say I agree with what it says :slight_smile:

Ashley

[1] http://nwrug.org/events/october09/


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

2009/10/14 Joaquin Rivera P. [email protected]

def other_complex_methods …
joaquin


www.least-significant-bit.com


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

An interesting standard to apply to your complex methods (well I think
its
interesting and valuable) is this

A method can either do one thing or call other methods but not both.
A method cannot be more than 5 lines long (insert a bigger number if 

you
must …)
If a method consists of calls to other methods then the names of
these
methods should document the method.

If you apply this to refactor your existing code you should end up with
a
hierarchy of small private methods with leaves that do tiny little tasks
and
nodes that describe how tasks are done. I find this beneficial in itself
(the code is much easier to read) as well as being a good first step to
extracting new objects. Nodes in the old object become public methods
and
their leaves come along as private methods in the new object.

You can take this further and state that no public method should ever do
anything, it should just contain calls to private methods which document
how
the public method works. I expect most would consider that going to far

sigh

Andrew

On Wed, Oct 14, 2009 at 4:47 PM, Ashley M.
[email protected] wrote:

I don’t think Scott meant to imply that private methods are bad, only that
complex ones private methods are.

This is a good point. I was overgeneralizing the response, despite
the question being somewhat more specific. My bad.

(It’s a worthwhile discussion, though.)


Have Fun,
Steve E. ([email protected])
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org

On Wed, Oct 14, 2009 at 7:07 PM, Ashley M.
[email protected] wrote:

On 14 Oct 2009, at 22:48, Matt W. wrote:

By the way, Sprout Class comes from ‘Working Effectively with Legacy Code’
(Feathers), which is probably the best book I’ve read on TDD (Admittedly
I’ve yet to read The RSpec Book). Highly recommended.

I’ve heard good things about this book too. Do you also recommend xUnit
Patterns?

It’s been a while since I’ve read that book. From what I remember it
had a lot of great information, but there were many sections I don’t
find applicable for my coding practices. I think a lot of the typical
xUnit styles of testing are heavily influenced from heavier weight
languages (like Java for instance). I think that is reflected in much
of the material in the book.

I did enjoy reading it over a few month period because of the wealth
of information, but I would consider many of the techniques dated
given where the current state of tools (RSpec and Cucumber), the
flexibility of our ruby, and the philosophy of BDD have put us.

So if you’re looking to read it for immediately applicable techniques
I would say don’t bother, but if you’re an information-whore and want
to gain a wealth of knowledge, and want to see a lot of thinking and
techniques that have influenced a lot of today’s tools and thinking,
then read it, for sure, but don’t expect to read it in a weekened or
even a week… that would be information overload – your brain would
explode.

Zach

[1] http://nwrug.org/events/october09/


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users


Zach D.
http://www.continuousthinking.com (personal)
http://www.mutuallyhuman.com (hire me)
http://ideafoundry.info/behavior-driven-development (first rate BDD
training)
@zachdennis (twitter)

On Thu, Oct 15, 2009 at 3:59 AM, Andrew P. [email protected]
wrote:

You can take this further and state that no public method should ever do
anything, it should just contain calls to private methods which document how
the public method works. I expect most would consider that going to far …
sigh

Once complexity has been managed, what’s the value of that strategy?


Have Fun,
Steve E. ([email protected])
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org

2009/10/15 Stephen E. [email protected]

Once complexity has been managed, what’s the value of that strategy?

I wrote a bit more about this in a blog article some time ago (
http://blog.andrew.premdas.org/articles/2009/04/07/writing-classes-why-its-so-easy-to-do-it-wrong-in-ruby).
I’m afraid my blog is fundamentally anti-social, and can be a bit flakey
on
up time so apologies if article is hard to access.

Fundamentally the reason for following this approach is to have code you
can
come back to and work on easily. If the public methods of a class
document
essentially the algorithm of how the class fulfils it function, and hide
the
detail then its much easier to come back to the code and work on it.

class Car
   def start
     turn_the_key
     pump_fuel_into_engine
     spark
  end

of course that was all well and good in the eighties, but in the late
oughties we need to update

class Car
   def start
     check_the_key_security_code
     boot_the_engine_management
     pump_fuel_into_engine
     spark

Not the greatest example I’m afraid (especially as I don’t drive and now
nothing about cars), but hopefully you get the idea

All best

Andrew

On Wed, Oct 14, 2009 at 15:36, Joaquin Rivera P.
[email protected] wrote:

def other_complex_methods …

and the two complex methods can get really tricky to get right, I would like
to be able to write specs for them, how do you do that? I mean I cannot do:

object.some_private_method

am I?

Hello, Joaquin.

I typically make these methods public, then test them. I use the
guideline “if it’s important enough to test, then it’s useful enough
to use somewhere else”. I usually end up using the method – or
something like it – somewhere else in my code base, then make it
public at that point, anyway.

I have also trusted, for a long time, the idea that if I want to test
it, but it’s private, then I really have a small object trying to grow
out of a larger object. I find this especially true when I have three
private methods, all related to each other, in the same class. In that
case I see the clear signal that a smaller object is getting out, so I
let that happen.

Of course, not everyone feels comfortable with so many small objects,
and not everyone feels comfortable making those methods public. If you
don’t feel comfortable to do that, then you should look for tricks in
Ruby to let you invoke that private method another way. I think
someone else suggested using send() for that. I strongly prefer
not to do that, and when I do, I generally only do it as a first step
towards refactoring the code I’m testing.

Only you can decide what to do, but if you can’t decide, then I highly
recommend making the method public, then testing it. If that makes you
dislike the design, then create a new class for the method and move it
there, making it public.

I hope this helps you.

J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Diaspar Software Services :: http://www.diasparsoftware.com
Author, JUnit Recipes
2005 Gordon Pask Award for contribution to Agile practice :: Agile
2010: Learn. Practice. Explore.

On 15 Oct 2009, at 01:06, Zach D. wrote:

So if you’re looking to read it for immediately applicable techniques
I would say don’t bother, but if you’re an information-whore and want
to gain a wealth of knowledge, and want to see a lot of thinking and
techniques that have influenced a lot of today’s tools and thinking,
then read it, for sure, but don’t expect to read it in a weekened or
even a week… that would be information overload – your brain would
explode.

Thanks for the info. I think I’ll look at some other books on my list
first then, and come back to this when I run out.

Cheers
Ashley


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

Hello Joaquin,

On Wed, Oct 14, 2009 at 5:22 PM, Joaquin Rivera P.
[email protected] wrote:

def other_complex_methods …

  1. Make the method public in the test case
    complex methods, especially private ones.
    the public method the question arose…
    I might shift my focus from whether or not these methods should be
    made public or moved to another class and first make sure I had
    written examples that focused on the behaviour I was interested in. I
    have found that having those tend to be a good help when thinking
    about making private methods public. Even if you find you don’t need
    these methods to be public you will find the examples afford you a
    great deal of freedom to refactor that code in a number of ways or by
    simply leaving them as private methods all while leaving the examples
    intact.

and yeah, I think 5 it my favorite at the moment,
they don’t have to be
private anyway, also IMHO testing private methods through the public API
it’s not in general applicable (only thinking here, no code sample)…

but anyway I wanted to hear what you guys think about it

Behaviour first. That will help you identify if you’re dealing with
different responsibilities which might push you to extract a new
object, or if you’re dealing with logic that goes together (in which
you might keep well-named private methods), or if you want to pull out
some of the dry and boring math calculations out into a method on some
utility class.

If you put good examples in place you’ll be able to change your mind
later without having to maintain brittle specs while having a great
deal of freedom for re-organizing the implementation in a number of
imaginable ways.


Zach D.
http://www.continuousthinking.com (personal)
http://www.mutuallyhuman.com (hire me)
http://ideafoundry.info/behavior-driven-development (first rate BDD
training)
@zachdennis (twitter)

Break your object up. It’s too big.

On Wed, Oct 14, 2009 at 12:36 PM, Joaquin Rivera P.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs