This discussion is archived
1 2 3 Previous Next 33 Replies Latest reply: Mar 26, 2009 9:41 AM by 807588 RSS

Test Driven Desing and private methods

807588 Newbie
Currently Being Moderated
I am building code using Test Driven Design. But I am writing a module where I would like some methods to be private since the only have meaning internally in the class. But this leaves me with the problem of writing tests.

How does on use TTD on methods that are private?

EDIT:

Another thing, how do often do you define methods as private?

I think its nice to declare all methods thats used internally in a class as private (minimizes the popup list of available methods) since these methods are not meant to be used outside the class anyway.

Edited by: fedevaps on Mar 26, 2009 3:00 PM
  • 1. Re: Test Driven Desing and private methods
    JoachimSauer Journeyer
    Currently Being Moderated
    There are at least two approaches to unit testing: white box or black box.

    Black box testing means that you only care about the publicly visible API and don't care about its internals. In this case you wouldn't directly test the private method, but only the visible public methods (which can then use the private method). The advantage is that you can completely change the implementation of the class under test while still being able to run the same test.

    White box testing assumes some things about the implementation and has no problem with accessing protected/package protected methods of the class under test. This couples the test more closely with the code (making it less maintenance-friendly) but makes it easier to write some specific tests and allows a more thorough testing.

    Which one you choose is up to you.

    If you use white-box testing, then you could provide make the private method package-protected and put the test in the same package. Changing the Class under test so that it's easier to test is not necessarily a bad thing and might even enhance the overall design: classes that are easy to test are usually easy to use as well.
  • 2. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    Ok but is generally good practice to make all internal methods private or should they just be kept public unless the class contains extremely many internal methods?
  • 3. Re: Test Driven Desing and private methods
    JoachimSauer Journeyer
    Currently Being Moderated
    fedevaps wrote:
    Ok but is generally good practice to make all internal methods private or should they just be kept public unless the class contains extremely many internal methods?
    Personally I have relatively few private methods.

    And relatively few public methods.

    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.

    Making them public is definitely a bad idea. A class should have as small a public interface as possible (while it should be as extensive as necessary).
  • 4. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    You can always play games with reflection:
    public class HasAPrivateMethod {
        private void aMethod() {
            System.out.println("I am private");
        }
    }
    import java.lang.reflect.*;
    
    public class Tester {
        public static void main(String[] args) throws Exception {
            HasAPrivateMethod obj = new HasAPrivateMethod();
    
            Method m = HasAPrivateMethod.class.getDeclaredMethod("aMethod");
            m.setAccessible(true); //bingo!
            m.invoke(obj);
        }
    }
    I hasten to add that I never do that. Since I've become test-infected, methods I would have previously made private that I want to write unit tests for I now give the default access level (package). I don't see much of a down side to that. You should be disciplined enough not to call the method within your package if it is given that access only for the sake of testing. Sometimes I think I should use a naming convention like starting such method names with an underscore...

    By the way, I have to disagree with Joachim. I'm cautious about making a method protected. Protected says to me: subclass and override me, but you really have to put in extra work to turn an ordinary class into one that can be subclassed successfully. At the very least you need to sit down and think harder about it. For that reason, I'm stingier with protected methods.
  • 5. Re: Test Driven Desing and private methods
    791266 Explorer
    Currently Being Moderated
    I think I should use a naming convention like starting such method names with an underscore...
    Why? I personally hate such conventions.

    Kaj
  • 6. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    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
    ++

    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.
  • 7. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    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+ ".

    Anyway, here's the scenario: some methods have the default level of access because they are meant to be called by other objects within the same package. Other methods have the default level of access only because I want to test them, and they shouldn't be called by other non-testing objects within the same package. How to discriminate?
  • 8. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    tsith wrote:
    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.
    How do you test your private methods?
  • 9. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    BigDaddyLoveHandles wrote:
    You can always play games with reflection:
    public class HasAPrivateMethod {
    private void aMethod() {
    System.out.println("I am private");
    }
    }
    import java.lang.reflect.*;
    
    public class Tester {
    public static void main(String[] args) throws Exception {
    HasAPrivateMethod obj = new HasAPrivateMethod();
    
    Method m = HasAPrivateMethod.class.getDeclaredMethod("aMethod");
    m.setAccessible(true); //bingo!
    m.invoke(obj);
    }
    }
    I hasten to add that I never do that. Since I've become test-infected, methods I would have previously made private that I want to write unit tests for I now give the default access level (package). I don't see much of a down side to that. You should be disciplined enough not to call the method within your package if it is given that access only for the sake of testing. Sometimes I think I should use a naming convention like starting such method names with an underscore...
    the downside to me is having methods in your class whose sole purpose is to test. This seems wrong.

    If there are private methods which are not called then they should be removed.
    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)

    That's how I see it, anyway.
  • 10. Re: Test Driven Desing and private methods
    791266 Explorer
    Currently Being Moderated
    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) :)
  • 11. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    tsith wrote:
    the downside to me is having methods in your class whose sole purpose is to test. This seems wrong.
    Either I am misunderstanding this statement, or you are misunderstanding me. I don't put testing code in ordinary classes. I think I follow the usual unit testing practice: I have a parallel directory structure that holds the testing code.

    >
    If there are private methods which are not called then they should be removed.
    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)

    That's how I see it, anyway.
    I tried to be careful with my wording: "methods I would have previously made private that _I want to write unit tests for_ I now give the default access level". A simple private method doesn't needed to be tested in isolation.
  • 12. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    BigDaddyLoveHandles wrote:
    tsith wrote:
    the downside to me is having methods in your class whose sole purpose is to test. This seems wrong.
    Either I am misunderstanding this statement, or you are misunderstanding me. I don't put testing code in ordinary classes. I think I follow the usual unit testing practice: I have a parallel directory structure that holds the testing code.
    Ah, I misunderstood you. Amend my post to say "The downside to me is having methods on your class's public interface whose sole purpose is to test".

    >
    >>
    If there are private methods which are not called then they should be removed.
    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)

    That's how I see it, anyway.
    I tried to be careful with my wording: "methods I would have previously made private that _I want to write unit tests for_ I now give the default access level". A simple private method doesn't needed to be tested in isolation.
    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?
  • 13. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    tsith wrote:
    BigDaddyLoveHandles wrote:
    tsith wrote:
    the downside to me is having methods in your class whose sole purpose is to test. This seems wrong.
    Either I am misunderstanding this statement, or you are misunderstanding me. I don't put testing code in ordinary classes. I think I follow the usual unit testing practice: I have a parallel directory structure that holds the testing code.
    Ah, I misunderstood you. Amend my post to say "The downside to me is having methods on your class's public interface whose sole purpose is to test".
    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?

    If there are private methods which are not called then they should be removed.
    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)

    That's how I see it, anyway.
    I tried to be careful with my wording: "methods I would have previously made private that _I want to write unit tests for_ I now give the default access level". A simple private method doesn't needed to be tested in isolation.
    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.
  • 14. Re: Test Driven Desing and private methods
    807588 Newbie
    Currently Being Moderated
    BigDaddyLoveHandles wrote:
    tsith wrote:
    BigDaddyLoveHandles wrote:
    tsith wrote:
    the downside to me is having methods in your class whose sole purpose is to test. This seems wrong.
    Either I am misunderstanding this statement, or you are misunderstanding me. I don't put testing code in ordinary classes. I think I follow the usual unit testing practice: I have a parallel directory structure that holds the testing code.
    Ah, I misunderstood you. Amend my post to say "The downside to me is having methods on your class's public interface whose sole purpose is to test".
    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.

    >
    If there are private methods which are not called then they should be removed.
    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)

    That's how I see it, anyway.
    I tried to be careful with my wording: "methods I would have previously made private that _I want to write unit tests for_ I now give the default access level". A simple private method doesn't needed to be tested in isolation.
    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.
    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?
1 2 3 Previous Next