14

I am trying to improve how I write my unit test cases for my Python programs. I am noticing in some cases, it would be really helpful to have access to private members to ensure that a method is functioning properly. An example case would be when trying to test a method for proper behavior that has no expected return value other than None. I know the easy and wrong way of doing this would be to just make the private attributes into protected attributes instead and test them directly. However, I would like to find a way that doesn't expose the interface as much.

So how do I test private attributes within classes without exposing them in the interface, or, if applicable, a better way of testing such a scenario so that private attribute access would not necessarily be needed for proper unit testing?

grg-n-sox
  • 717
  • 2
  • 5
  • 25
  • 4
    What are "private" and "protected" attributes supposed to be in Python? There are no such things. – Sven Marnach Nov 08 '11 at 15:28
  • 7
    This is a touchy subject; some guidelines say if it's private it doesn't need to be tested! – corsiKa Nov 08 '11 at 15:28
  • @Sven what about `_var1` and `__var2` as protected and private, respectively? – corsiKa Nov 08 '11 at 15:30
  • I am agree with @glowcoder, your unit tests are supposed to test only exposed functionality of your objects. Thus, if something is hidden, only internal methods should use it. All you (and your tests as well) need to know (and test) about your object - are public properties. – ikostia Nov 08 '11 at 15:31
  • @glowcoder: That's stretching the analogy a bit too far. Moreover, a unit test could simply access these attributes (anyone could). – Sven Marnach Nov 08 '11 at 15:32
  • @Sven so those are merely 'convention' (term used lightly), not enforced by the language? – corsiKa Nov 08 '11 at 15:33
  • @glowcoder: No, they aren't enforced. `__var` induces some name mangling, though. – Sven Marnach Nov 08 '11 at 15:39
  • 1
    Sometimes it's useful to be able to test internal methods of your class, because all the paths to properly test them would be too comlicated when called from public methods. But that usually means your class needs split-refactoring into multiple smaller bits, so I'd go with everyone else: private, don't test. It should be covered by your tests of the public methods. – Guillaume Nov 08 '11 at 16:45
  • @Guillaume Your first sentence says what everyone thinks on first glance. Then upon further consideration you realize that if it's that complex it needs its own class anyway. :-) I couldn't have put the logical progression of "we need this" to "we don't need this" any better! :-) – corsiKa Nov 08 '11 at 19:01
  • Sorry for the confusion guys. When I say private and protected, I mean what glowcoder said with _var1 and __var2 being protected and private, respectively. I know it is technically just a convention more than anything else but I like to always code as if that is enforced by the language. That being said, it is not so much due to complexity issues that I want to be able to do this. It is just that I have methods that just execute a routine but do not return any object, so there is nothing to black box test in isolation other than that it does not return an unexpected exception. – grg-n-sox Nov 08 '11 at 19:11

2 Answers2

23

Nothing is private in Python. If you are using the double underscore prefix on member variables, the name is simply mangled. You can access it by qualifying the name in the form _Class__member. This will access the __member variable in the class Class.

See also this question: Why are Python's 'private' methods not actually private?

Community
  • 1
  • 1
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
4

I'm gonna go off in a different direction...

Try to write unit tests that assert public behavior over private state. Lets say you call your void method A() that modifies internal state. Now if the method is called and the state does change, there will be some observable change in your little code-universe. Maybe B() now behaves differently. So my test would be... (trivializing the example)

void MyTest()
{
   Assert.That(B(), Is.False);
   A();
   Assert.That(B(), Is.True);
}

Avoid Inappropriate Intimacy between the test and the SUT.

Gishu
  • 134,492
  • 47
  • 225
  • 308
  • Thanks, this is much more along the lines of an answer I was hoping for. Is Inappropriate Intimacy a different name for the anti-pattern/code small known as object orgy? And if I am trying to test something like a concrete command class's execute() method from the command design pattern, how would I test such a function if it relies on other method calls to change the state, especially state that is outside the scope of the command class? – grg-n-sox Nov 09 '11 at 14:38
  • 1
    @grg-n-sox :A command class acts on a command target. So you could create a command object passing in the target as a ctor parameter. Call Execute and then assert on the expected change on the command target. OR you could isolate the target from the command by creating a target interface / role between them. Then you pass in a mock command as the ctor parameter & just assert that the command is calling the right methods on the interface. – Gishu Nov 10 '11 at 03:01
  • 2
    I'm not sure that inappropriate intimacy is a good thing 100% of time for unit tests. When your tests are embedding a complex logic, if you want them to be **unit** tests it's better to test the small component of this logic. – AsTeR Oct 05 '13 at 17:04