On Wed, Oct 14, 2009 at 5:49 PM, Scott Taylor <scott at railsnewbie.com> wrote:> > On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: > > 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 > > 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). > Scott3 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> > am I? > > thanks in advance, > joaquin > > -- > www.least-significant-bit.com > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Wed, Oct 14, 2009 at 3:49 PM, Scott Taylor <scott at railsnewbie.com> 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 Eley (sfeley at gmail.com) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org
On 14 Oct 2009, at 20:49, Scott Taylor wrote:> On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: > >> 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 > > 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).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 http://aviewfromafar.net/
On Oct 14, 2009, at 4:24 PM, Nicol?s Sanguinetti wrote:> On Wed, Oct 14, 2009 at 5:49 PM, Scott Taylor > <scott at railsnewbie.com> wrote: >> >> On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: >> >> 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 >> >> 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 > > 3 is ok.Yeah, 3 is OK, although ideally you *are* testing the method, albeit indirectly through the public interface. Scott> > 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 > >> >> am I? >> >> thanks in advance, >> joaquin >> >> -- >> www.least-significant-bit.com >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On 14 Oct 2009, at 21:31, Stephen Eley 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. > > <snip> > > 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 http://aviewfromafar.net/
On 14 Oct 2009, at 20:49, Scott Taylor wrote:> On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: > >> hello there, >> how do you tipically spec private methods? The thing is ? have >> something like this: > > 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).Yup. Sprout class[1] works for me, every single time. [1]http://xunitpatterns.com/Sprout%20Class.html cheers, Matt +447974 430184 matt at mattwynne.net http://mattwynne.net
On 14 Oct 2009, at 22:33, Matt Wynne wrote:> > On 14 Oct 2009, at 20:49, Scott Taylor wrote: > >> On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: >> >>> hello there, >>> how do you tipically spec private methods? The thing is ? have >>> something like this: >> >> 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). > > Yup. Sprout class[1] works for me, every single time. > > [1]http://xunitpatterns.com/Sprout%20Class.htmlBy 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 > matt at mattwynne.net > http://mattwynne.net >cheers, Matt +447974 430184 matt at mattwynne.net http://mattwynne.net
On 14 Oct 2009, at 22:48, Matt Wynne 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 :) Ashley [1] http://nwrug.org/events/october09/ -- http://www.patchspace.co.uk/ http://www.linkedin.com/in/ashleymoran http://aviewfromafar.net/
On Wed, Oct 14, 2009 at 7:07 PM, Ashley Moran <ashley.moran at patchspace.co.uk> wrote:> > On 14 Oct 2009, at 22:48, Matt Wynne 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> > 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 :) > > Ashley > > [1] http://nwrug.org/events/october09/ > > -- > http://www.patchspace.co.uk/ > http://www.linkedin.com/in/ashleymoran > http://aviewfromafar.net/ > > > > > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Zach Dennis http://www.continuousthinking.com (personal) http://www.mutuallyhuman.com (hire me) http://ideafoundry.info/behavior-driven-development (first rate BDD training) @zachdennis (twitter)
On Wed, Oct 14, 2009 at 4:47 PM, Ashley Moran <ashley.moran at patchspace.co.uk> 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 Eley (sfeley at gmail.com) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org
On Thu, Oct 15, 2009 at 3:59 AM, Andrew Premdas <apremdas at gmail.com> 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 ... > sighOnce complexity has been managed, what''s the value of that strategy? -- Have Fun, Steve Eley (sfeley at gmail.com) ESCAPE POD - The Science Fiction Podcast Magazine http://www.escapepod.org
On Wed, Oct 14, 2009 at 15:36, Joaquin Rivera Padron <joahking at gmail.com> wrote:> 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?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.
Hello Joaquin, On Wed, Oct 14, 2009 at 5:22 PM, Joaquin Rivera Padron <joahking at gmail.com> wrote:> hello > > 2009/10/14 Ashley Moran <ashley.moran at patchspace.co.uk> >> >> On 14 Oct 2009, at 20:49, Scott Taylor wrote: >>> >>> On Oct 14, 2009, at 3:36 PM, Joaquin Rivera Padron wrote: >>> >>>> 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 >>> >>> 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). >> >> 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? > > 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...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 itBehaviour 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 Dennis http://www.continuousthinking.com (personal) http://www.mutuallyhuman.com (hire me) http://ideafoundry.info/behavior-driven-development (first rate BDD training) @zachdennis (twitter)
On 15 Oct 2009, at 01:06, Zach Dennis 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 http://aviewfromafar.net/
Break your object up. It''s too big. On Wed, Oct 14, 2009 at 12:36 PM, Joaquin Rivera Padron <joahking at gmail.com> wrote:> 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 > > -- > www.least-significant-bit.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >