1 2 3 Previous Next 33 Replies Latest reply on Mar 26, 2009 7:38 PM by jschellSomeoneStoleMyAlias Go to original post
      • 15. Re: Test Driven Desing and private methods
        807588
        tsith wrote:
        BigDaddyLoveHandles wrote:
        All I'm doing is promoting some methods that would have otherwise been private to the default level. That doesn't count as "having methods on your class's public interface" does it?
        Well, to me, yeah - I mean, you said "you should have the discipline not to call them outside the class" - which seems a little risky. I suppose with your naming convention, or maybe creative use of annotations, you could mitigate that risk, but still.
        I admit I'm not entirely happy with the result.
        No. Consider a private method that is passed arguments, for example. Its spec may assert it has certain behaviour when passed certain values. It may be hard or impossible to pass those values through the public methods that call it, so I want to test it separately.
        Ah, I see. But I don't know - if it's hard or especially impossible to pass those values through the public methods, then why test that case?
        I would turn the question around: why was that code factored into a private method? For me, there are two related reasons: code reuse, and to be able to abstract it away as chunk of code with a spec, so that it is easier to reason about. And I want to test that spec to gain confidence in it.

        As for why test the "impossible" -- often these are error conditions, and I'd like to verify the robustness of the code.

        -----

        Story time:

        My manager was a little shaky on unit testing. He wanted us to write some "round-trip" tests for a web app. Testing web apps is my white whale! Of course, unit-testing is just one phase of testing -- it doesn't replace acceptance testing etc... but I pointed out that if a round-trip test fails, we still need to narrow down the failure, and I'd rather that was done with smaller tests that by me sitting down to do some good old-fashioned ad hoc debugging. Therefore:

        if a round-trip test fails then there should be a unit-test that fails for the same reason.

        If not, then for me that implies the design needs to be improved. The failure should be an observable thing that can be spotted in a smaller test.

        What about the converse:

        if a unit test fails then there should be a round-trip test that fails for the same reason.

        This might not be the case: imagine a small part on your car's engine fails, but the engine compensates and continues to run. Still, I prefer the over-engineering this implies. Not only does the whole function according to spec, but each part does as well.
        • 16. Re: Test Driven Desing and private methods
          807588
          BigDaddyLoveHandles wrote:
          tsith wrote:
          BigDaddyLoveHandles wrote:
          All I'm doing is promoting some methods that would have otherwise been private to the default level. That doesn't count as "having methods on your class's public interface" does it?
          Well, to me, yeah - I mean, you said "you should have the discipline not to call them outside the class" - which seems a little risky. I suppose with your naming convention, or maybe creative use of annotations, you could mitigate that risk, but still.
          I admit I'm not entirely happy with the result.
          No. Consider a private method that is passed arguments, for example. Its spec may assert it has certain behaviour when passed certain values. It may be hard or impossible to pass those values through the public methods that call it, so I want to test it separately.
          Ah, I see. But I don't know - if it's hard or especially impossible to pass those values through the public methods, then why test that case?
          I would turn the question around: why was that code factored into a private method? For me, there are two related reasons: code reuse, and to be able to abstract it away as chunk of code with a spec, so that it is easier to reason about. And I want to test that spec to gain confidence in it.
          But arguably the only part of the spec that "matters" is the part that is exercised by your public methods. If later on some part of that spec is used by a modification to the public interface of your class then the UT for that modification will exercise that part of the spec.

          >
          As for why test the "impossible" -- often these are error conditions, and I'd like to verify the robustness of the code.
          Yes, this is a problem for me as well. If I want to know if my error handling code is right, but producing the error is difficult if not impossible, then - yeah, that's a problem for me as well.
          • 17. Re: Test Driven Desing and private methods
            807588
            tsith wrote:
            But arguably the only part of the spec that "matters" is the part that is exercised by your public methods. If later on some part of that spec is used by a modification to the public interface of your class then the UT for that modification will exercise that part of the spec.
            This is where programming becomes as much as an art as a science. We want to be able to decompose and examine the parts in isolation. Specifications facilitate that. To say only part of the spec "matters" is to start back sliding about the compositional nature of what we are trying to do. In that case, one could tweak the spec, but to argue that the spec is covered by how other code uses it is not a compositional argument -- we are no longer looking a the code at hand in isolation, but at how other implementations use it, and I worry that kind of reasoning can get out of hand.
            • 18. Re: Test Driven Desing and private methods
              807588
              >
              If your private methods are called, then the tests that exercise the public methods which call those private methods should test the private methods (fire up a code coverage tool to see)
              >
              I totally agree. Why would you test a Method 2-n times?

              >
              And while we're proffering up our opinions - I make everything private and then make only what needs to be public public. I rarely use protected or package private.
              >
              >
              If I have some internal methods that help doing the stuff that the public are supposed to do, I usually make them protected. This way they can be overridden and used by derived classes and are still not visible to everyone.
              >
              You both are right. If you're working on something like a framework, you do protected, otherwise, the developer's possibilites are limited. ... and for private method, no good example crosses my mind (jesus....).

              regards
              slowfly
              • 19. Re: Test Driven Desing and private methods
                807588
                This sometimes bugs me, in unit testing:
                public void f(X x) {
                   ...
                   Y y = x.g();
                   ...
                }
                If I want to unit test method f, I can always pass a mock object in for x -- being good coders, X is an interface.

                But what about:
                public void f() {
                   ...
                   Y y = this.g();
                   ...
                }
                Different rules apply?
                • 20. Re: Test Driven Desing and private methods
                  807588
                  BigDaddyLoveHandles wrote:
                  tsith wrote:
                  But arguably the only part of the spec that "matters" is the part that is exercised by your public methods. If later on some part of that spec is used by a modification to the public interface of your class then the UT for that modification will exercise that part of the spec.
                  This is where programming becomes as much as an art as a science. We want to be able to decompose and examine the parts in isolation. Specifications facilitate that. To say only part of the spec "matters" is to start back sliding about the compositional nature of what we are trying to do. In that case, one could tweak the spec, but to argue that the spec is covered by how other code uses it is not a compositional argument -- we are no longer looking a the code at hand in isolation, but at how other implementations use it, and I worry that kind of reasoning can get out of hand.
                  But in my mind we stopped looking at the code at hand in isolation as soon as we marked it private. That's one step up from inlining it, to me. And I think there are good reasons to mark something private. And one of those reasons is that this code makes no sense outside the context of the class it's in. Thus, I don't think it makes sense to build UTs around this code, but rather build them around the public interface of the class.
                  • 21. Re: Test Driven Desing and private methods
                    807588
                    BigDaddyLoveHandles wrote:
                    This sometimes bugs me, in unit testing:
                    public void f(X x) {
                    ...
                    Y y = x.g();
                    ...
                    }
                    If I want to unit test method f, I can always pass a mock object in for x -- being good coders, X is an interface.

                    But what about:
                    public void f() {
                    ...
                    Y y = this.g();
                    ...
                    }
                    Different rules apply?
                    If I take your meaning, I agree - methods with no publicly-accessible effects are both hard to test and design red-flags, in my experience.
                    • 22. Re: Test Driven Desing and private methods
                      807588
                      tsith wrote:
                      But in my mind we stopped looking at the code at hand in isolation as soon as we marked it private. That's one step up from inlining it, to me. And I think there are good reasons to mark something private. And one of those reasons is that this code makes no sense outside the context of the class it's in. Thus, I don't think it makes sense to build UTs around this code, but rather build them around the public interface of the class.
                      I think we've come full circle, so I'll stop. Thanks everybody for your comments!

                      -- Arbuthnot
                      • 23. Re: Test Driven Desing and private methods
                        807588
                        One final shot across the bow:

                        Testing is so important, one may want features in the programming languages to help support it.

                        If you find yourself changing your design to make it more testable and that improves the design in general, it's a win.

                        But what if you find making changes just for the sake of testing?
                        • 24. Re: Test Driven Desing and private methods
                          807588
                          BigDaddyLoveHandles wrote:
                          One final shot across the bow:

                          Testing is so important, one may want features in the programming languages to help support it.

                          If you find yourself changing your design to make it more testable and that improves the design in general, it's a win.

                          But what if you find making changes just for the sake of testing?
                          like, making things that should be private non-private ;-)

                          Yes, I agree - the more I get into it the more I think annotations and more Design-By-Contract support would be a Good Thing - but then I run into your query there.
                          • 25. Re: Test Driven Desing and private methods
                            jwenting
                            kajbj wrote:
                            BigDaddyLoveHandles wrote:
                            kajbj wrote:
                            I think I should use a naming convention like starting such method names with an underscore...
                            Why? I personally hate such conventions.

                            Kaj
                            Notice I wrote "I think I +should+ ".
                            I saw that, but couldn't find a good reason to considering the bad convention (IMHO) :)
                            well said. There is no good reason.

                            Unit tests are designed to test the public interface, anything else is an implementation detail that either gets called through the public interface of doesn't get called at all in which case it should be eliminated from the codebase.
                            If something gets so complex you can't keep track of the depth of the method calls, you need to break up those classes into smaller ones that do have more shallow code paths and public interfaces to test those paths independently.

                            Any time you think you need method naming cnnventions to indicate which methods are supposed to called from where, there's something incredibly fishy in your design.
                            • 26. Re: Test Driven Desing and private methods
                              807588
                              jwenting wrote:
                              Unit tests are designed to test the public interface, anything else is an implementation detail that either gets called through the public interface of doesn't get called at all in which case it should be eliminated from the codebase.
                              If something gets so complex you can't keep track of the depth of the method calls, you need to break up those classes into smaller ones that do have more shallow code paths and public interfaces to test those paths independently.
                              <weeps>Such tough love! This reminds me of my Mallow Bar intervention.</weeps>

                              So if I have a private method in a class that I would like to unit test, I could refactor it as a public method in a (perhaps) new helper class, that becomes an implementation detail of the original class? Hmmm... not bad.
                              • 27. Re: Test Driven Desing and private methods
                                807588
                                BigDaddyLoveHandles wrote:
                                jwenting wrote:
                                Unit tests are designed to test the public interface, anything else is an implementation detail that either gets called through the public interface of doesn't get called at all in which case it should be eliminated from the codebase.
                                If something gets so complex you can't keep track of the depth of the method calls, you need to break up those classes into smaller ones that do have more shallow code paths and public interfaces to test those paths independently.
                                <weeps>Such tough love! This reminds me of my Mallow Bar intervention.</weeps>
                                Thank you for the visual.
                                So if I have a private method in a class that I would like to unit test, I could refactor it as a public method in a (perhaps) new helper class, that becomes an implementation detail of the original class? Hmmm... not bad.
                                Stop testing private things!! Leave them alone! They're just sitting there, not bothering anyone, no connection to the outside world, and suddenly wham jUnit to the solar plexus!


                                /wanders off to get a Snickers.
                                • 28. Re: Test Driven Desing and private methods
                                  807588
                                  tsith wrote:
                                  /wanders off to get a Snickers.
                                  Regular, Dark or Almond?
                                  • 29. Re: Test Driven Desing and private methods
                                    jschellSomeoneStoleMyAlias
                                    BigDaddyLoveHandles wrote:
                                    I must not be understanding you - why do you want to test a private method? Isn't it already tested in the UT for the public method(s) that it is called from?
                                    No. Consider a private method that is passed arguments, for example. Its spec may assert it has certain behaviour when passed certain values. It may be hard or impossible to pass those values through the public methods that call it, so I want to test it separately.
                                    Impossible?

                                    They are private. The other methods do not use the functionality. Thus nothing can use the functionality.

                                    Why does it exist then?

                                    Conversely if you find it necessary to have code that isn't actually used then myself I would prefer that a test for it exists. At least then two years from now when I need to modify that class, I might not know that the code is absolutely useles, but at least I can be assured that the changes that I make don't break it.