Use private method tests as scaffolding that eventually gets removed as more abstract (but still fast) tests test the same stuff. tag-removing-tests
perhaps if you want to test your private methods you've identified another class's public interface
On podcast-giant-robots-145 Ben talks about iceberg-class, and him and his guest talk about how someone made their private methods public to be able to test them, and how that really pointed to the class being too big.
blog-post-mark-methods-private-when-you-do-not-test-them
In talk-the-deep-synergy-between-testability-and-good-design Michael Feathers talks about whether you should test private methods or not.
From http://rubyrogues.com/087-rr-book-clubpractical-object-oriented-design-in-ruby-with-sandi-metz/
CHUCK: Can I push back on something really quick on that and that is that a lot of times, I'll compose methods out of private methods. And most of the time, you're right that you test your public method, you test what comes in and goes out. And that's fine. But sometimes, I kind of codified a complex sequence of things I have to happen into a method on a class. And a lot of that winds up in private methods just so that I can say, "Look, this is the interface you want to use. And the rest of the stuff just makes it so that I can read what I put into my public method." I can't get to those private methods directly. And so, it usually turns into a battery of a whole bunch of tests to manage the complex process that's there.
Is that an indication that I have a problem?
JAMES: Yes.
CHUCK: Or is that something that I may have to reach in and test my privates?
JAMES: Nope. It is a common problem actually. And I have a pick for this episode that's exactly about that. So, how about we save it for there?
SANDI: So does that mean I shouldn't express anything?
JAMES: You can but…[crosstalk]
CHUCK: Express please.
SANDI: Here's what I would say. Don't test private methods unless you really need to. In which case, test them as much as you want. I have code, and this is what happens, right?
DAVID: I love you, Sandi. I love you so much!
SANDI: Here's the deal. So, you have private methods and there are nasty gnarly complicated unstable things. And if you just test the edges, if you just follow the rules I gave you and test the boundaries of your interface, if you screw up a private method then it's really hard to fix it because the error message is a long way from the thing that failed.
So, the writing test of private method means that you're writing a test that tightly couples you to something that's unstable. And there's a cost and a benefit to that. If you break it, if it ought to work and you break it accidentally, your test will tell you — they will drive you very close to where the problem is and make it easy to fix. However, if you decide on a different — if you decide to change that unstable private implementation to something else, then you have to throw your test away and write a new one.
It may be that it's worth it to you to test a private method because — when I'm writing a new class, I often have tests for all the private methods in it. And then as things settle down and I feel like the private implementation maybe is more steady, at that point, either I take the test of the private method out or I put a little note in there that says, "If these break, delete them."
DAVID: You uttered a heresy that just lit me up so happily. You did a Lunch n' Learn at Heroku and you talked about testing. And you talked about testing private methods and you got through the, "If it's hard, go ahead and test this so that you can work your way through it."
And then you said something that made my jaw hit my chest. You said, "And then once it's working, delete the test."
SANDI: Yeah. You don't need it. It's just in your way.
DAVID: It's in the way of anybody who comes after.
From http://rubyrogues.com/158-rr-confessions/ at about ten minutes in:
DAVID: I came across a really interesting ripple in testing thought, because I used to bang on all the time about yes, you should test your private methods. If it can possible break, you should test it. And counterargument is you should test your private methods through the public interface. And my reply to that is, "But that's a level of indirection. That's a level of impedance, impedance mismatch." And you can go around the table and around the table and around the table. And I finally found out that the people that are saying never test your private methods are almost exclusively talking about regression testing, because they want to be able to change the private method and not break a fragile test framework.
AVDI: Right.
DAVID: Where people like me that are talking about wanting to test private methods are people who may have no idea how they're going to solve this problem. They're venturing into the deep, dark jungle and they want to use their testing framework as headlights into the park right ahead. And boy, you do. You want to test private methods. You want to test every little piece, because you're cutting gears out on the metal shop floor and you want to assert that that gear works correctly before you stick it in the machine that you don't know is going to work at the end of the day
AVDI: Right.
DAVID: But at the end of the day, and that's how I finally spiritually reached this level of acceptance with myself of when I am driving the design forward, I will test private methods. And then at the end of the day, I rip those tests out and I throw them away.
AVDI: Right.
DAVID: Because they are not only worthless as regression tests but they actually have negative value. They will cost you money if you leave them in the codebase.
AVDI: Yes. I think that's a really important realization. And I feel very little compunction about throwing tests away.
CHUCK: Do you ever refactor them into the public interface tests?
DAVID: Sometimes. If a test, I get halfway through and I realize this isn't just a private method, this is actually something that has to be exposed, then sure. That test will percolate up.
CHUCK: Yeah. I wonder those sometimes. Like if you are breaking a call that does a lot of things down into the smaller tests to get it written and then they have side effects, you could put those assertions into the assertions on the higher level public method and then just trash the private methods test. Does that make sense?
DAVID: It does. And I'm going to disagree with you just a little bit. I could be wrong. But to me, that feels like something fragile. It feels like now if I go in and change the way that this class modifies its internal state or has, if I modify its side effects, my test suite could break even though the class is still working correctly. However, I don't run into that very often. And the reason why is because by about the 15th private method that you're testing on a class, I start to realize, "I think this class is doing too much."
[Laughter]
DAVID: And I suddenly discover that I've been building a god object. I've been building… I've started with a script file, I created an application class that does everything, and lo and behold, I've actually caught myself on this and broken the class into extracted classes from it and actually extracted six other classes from the class that I was working with. And I'm like, "Oh. That's why it hurts so bad. And once I extracted them, the classes that were extracted, they now have public interfaces. And those have to be tested.
AVDI: Right.
DAVID: And so, those tests survived. And so, anything that was causing a side-effect or was having an intermediate result, I usually have been able to design that away by extracting it out and testing it in isolation and then testing the connection between the two.
AVDI: I think I do basically the same thing. I just come at it from a slightly different angle than you. I never test private methods as a rule. What that really just means is that I test public methods and I basically only extract private methods, with some exceptions. If I have a private method, it was extracted out of a public method that I had already tested.
DAVID: Yeah.
AVDI: So, it's tested by definition. But then I think I probably just extract things out earlier than you do because once I get to that point where it's like, "Wow. I really want to reach into that private method to design something," I'm like, "Okay. So that means it's time to extract something out."
DAVID: Yeah.