The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Unit testing private members

While testing a class I need to check its internal data to verify some post-condition. I'm sure this is not a rare thing. I've seen somewhere that I might mean that my design is not good enough, but I don't see any reason to publicize the internal data just so that a unit test could check it.

In C++ I might add a friend clause for the class's TestCase, but in Java and C# I'd have to use reflection, which is quite ugly to look at, and those string names for methods don't refactor very well. Both solutions leave much to be desired.

It seems that any TestCase class should have unrestricted access to all private data members of all classes. After all, who wants to spend precious time creating an elaborate design for tests, that should be as simple as possible?

Isn't it time for those features to be introduced as native to languages, or at least for a Design Pattern that solves this problem?
Eli Golovinsky Send private email
Saturday, November 06, 2004
 
 
In Java, I place the TestCases in the same package as the class it tests and keep the access-level of  the data members at 'package'. This applies only to the data members that might need to be used by the TestCase, but when I actually look deep enough, I don't use these directly for testing. I stick to the public interface of the class, as this is the one that faces the outside world. I tease the class 'from a distance' as I have found these tests to be more benefitial.

Yeah, in C++ you would need to declare the TestCase as a 'friend', and you could enclose that with conditional compilation constructs like '#ifdef UNITTEST' so that you can rip these declarations away when releasing the build. Still looks ugly in code, can't do much about that. Again, you might be better off testing the class as a client without any private-access privileges.
subhash Send private email
Saturday, November 06, 2004
 
 
In C# the accessor would be "internal". It does roughly the same then "package" in Java.
Gerd Riesselmann
Saturday, November 06, 2004
 
 
Care to post more detail? There may be some reason why what you're doing is good. However, without further information I'ld be inclined to think it's sub-optimal design, and you'ld be better off improving the class instead of looking for ways to let your test code access the internals.

It definately sounds like the operation you're testing changes the object's internal state but leaves the logical state (what's publically visible) unchanged, or at least has minimal or hard to follow changes. That may make sense if it's one step in a long process, but that would at least make me wonder if the entire process should be redesigned.

If there is a block of operations that is genuinely an implementation detail why not split that into a separate class with its own public interface? Then the test code can use that section's public interface, and the 'real' clas that needs that functionality can embed the implementation object and use the same interface as the test code was using.

Saturday, November 06, 2004
 
 
There are already a lot of discussion about that: http://c2.com/cgi/wiki?ExtremeProgrammingTestingPrivateMethods

In my opinions... not all method should be included in test, we should test the function rather than test the implementation: http://xprogramming.com/xpmag/testFirstGuidelines.htm

So if you really think a private method should be in unittest, why don't just make it public?

BTW, there is already some lauguage support unittest as part of syntax... but our boss probably won't hire us to write those language: http://www.digitalmars.com/d/sdwest/page7.html
Carfield Yim Send private email
Sunday, November 07, 2004
 
 
I don't have a particular example of a time when I thought that testing a private member seemed reasonable handy. But these things have happened. Every time I had to refactor some code to make its unit-testing more straight forward I was feeling I was wasting my time.
Using mocks for instance, requires that all classes that can be replaced by mocks should implement an interface similar to the interface the class itself reveals (i.e. DB and MockDB implement IDB). That seems redundant in more than a few cases. Moreover, the users of the actual/mock class should allow plugging in a service class (i.e. a database service supporting IDB), and that too complicates the design unnecessarily. Most modern design techniques state that designs should be as simple as possible, and that's well.. that's not as simple as it should be.
Eli Golovinsky Send private email
Sunday, November 07, 2004
 
 
In Java you can do create a TestHelper object that gets you a value from an object like this:  The key is the field.setAccessible(true) call.  You can use this same idea for executing private/protected methods.
---
public static Object getObjectProperty(Object object, String fieldName) {
    try {
        java.lang.reflect.Field field = null;
        Class clazz = object.getClass();
        while (field == null) {
            try {
                field = clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException nsfe) {
                clazz = clazz.getSuperclass();
                if (clazz == Object.class )
                    break;
            }
        }
        field.setAccessible(true);
        Object value = field.get(object);
        return value;
    } catch (Exception e) {
        //do some thing here
    e.printStackTrace(System.err);
    }
    return null;
}
Brettt Send private email
Monday, November 08, 2004
 
 
Did anyone else giggle at the subject of this posting?  I know I did.
zigzag Send private email
Wednesday, November 10, 2004
 
 
You can use inner classes:

import junit.framework.TestCase;
public class TestingHiddenStuff {
      private int hiddenValue;
      public TestingHiddenStuff(int value) { hiddenValue = value;    }
      private int doubleIt() { return hiddenValue * 2; }
      private int trebleIt() { return hiddenValue * 3; }
      private int halveIt() { return hiddenValue / 2; }
      static public class InnerTest extends TestCase {
              TestingHiddenStuff ths;
              protected void setUp() { ths = new TestingHiddenStuff(8); }
              public void testHiddenValue() { assertEquals(8, ths.hiddenValue); }
              public void testDoubleIt() { assertEquals(16, ths.doubleIt()); }
              public void testTrebleIt() { assertEquals(24, ths.trebleIt()); }
              public void testHalveIt() { assertEquals(4, ths.halveIt()); }
      }
}

Theres a good summary of your options on Artima:
http://www.artima.com/suiterunner/private.html
Ged Byrne Send private email
Tuesday, November 16, 2004
 
 
I know that this feature exists in Whidbey based on this post:
 http://blogs.msdn.com/hongmeig/archive/2004/11/17/259250.aspx
Neyah
Friday, November 19, 2004
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz