1

I have a class that defines a private (well, __container to be exact since it is python) container. I am using the information within said container as part of the logic of what the class does and have the ability to add/delete the elements of said container.

For unit tests, I need to populate this container with some data. That data depends on the test done and thus putting it all in setUp() would be impractical and bloated -- plus it could add unwanted side effects.

Since the data is private, I can only add things via the public interface of the object. This runs code that need not be run during a unit test and in some cases is just a copy and paste from another test.

Currently, I am mocking the whole container but somehow it does not feel that elegant a solution. Due to Python mocking frame work (mock), this requires the container to be public -- so I can use patch.dict(). I would rather keep that data private.

What pattern can one use to still populate the containers without excercising the public method so I have data to test with?

Is there a way to do this with mock's patch.dict() that I missed?

4
  • 1
    You explictly don't need to make anything public. You can access _private members and __name_mangeled ones as well (the latter requires knowledge of the name mangling algorithm though, and is even more fragile). That doesn't mean you should though.
    – user7043
    Nov 15, 2011 at 17:10
  • @delnan: Indeed, you could write: patch.object(sut._ClassName__container, {...}) and that would do it. That would be a solution. If you wanted to write it up, I'd upvote you... Nov 15, 2011 at 17:18
  • I won't submit it as answer because it isn't a good answer. It technically answers your question and it's worth mentioning, but it doesn't solve your actual problem. I'd write up what I feel you should do instead, but I lack time and test guru-ness.
    – user7043
    Nov 15, 2011 at 17:30
  • I don't understand the question completely, but will the @property decorators help you? Nov 19, 2011 at 11:34

2 Answers 2

1

Until recently, I would have just pointed you at plenty of other existing questions that say that you generally shouldn't need access to any private stuff, in order to write unit tests - as the whole point of tests is to test the public (and protected) interface.

For example, in the question how to unit-test private methods in jquery plugins?, there is this answer:

The same applies here as with any other language and testing privates: To test private methods, you should exercise them via the public interface. In other words, by calling your public methods, the private methods get tested in the process because the public methods rely on the privates.

Generally private methods are not tested separately from the public interface - the entire point is that they are implementation details, and tests should generally not know too much about the specifics of the implementation

In your specific case, you say:

Since the data is private, I can only add things via the public interface of the object. This run codes that need not be run during a unit test and in some case is just a copy and paste from another test.

I would be cautious about having any tests that avoided code that normally needs to be run - for fear that your tests would spuriously pass, due to some difference between the test behaviour and the real world.

Having said all that, I recently learned about a really excellent article on writing testsuite called The Way of Testivus. It's a PDF that's only 12 pages long, and a really easy and enjoyable read.

What's relevant here is the section entitled "Sometimes, the test justifies the means" - in the context of violating encapsulation to enable testing. I highly recommend it.

(Another favourite of mine is "An ugly test is better than no test.")

So, in your context, if you still decide you really want a different way to set up data purely for tests, it might be reasonable to add a public setter method, specifically documented as only existing to aid writing of tests.

3
  • You misunderstood the question. I can test __container via the public interface, that is fine and indeed what you should do. However, I need to populate it to run other tests. Should I populate it via the public interface (clutter and copy and paste anti-patterns) or do I mock the private container or what else? The what else is what I want to know. Otherwise, just a best practice would be fine. Nov 16, 2011 at 8:05
  • I'm tempted to give you -1 for the part about reducing the quality of your code for the sake of unit testing
    – Ryathal
    Jan 11, 2012 at 18:47
  • Please understand that I was quoting from a publication (Testivus) and then read that for yourself! It really is an enjoyable and interesting read. Jan 11, 2012 at 23:05
0

The convention for private attributes is a single leading underscore; a double leading underscore is for protected (it will use name mangling to keep the attribute unique across subclasses).

class Test():
    _private = 1
    __protected = dict()
    __container = list()

If private is what you really want, just remove one of the leading underscores and then accessing and modifying _container is easy-peasy.

If protected is really what you want, you can still access __container but you'll have to mangle the name yourself if accessing it from outside the class. Using my Test class above to illustrate:

t = Test()
t.__Test_container.append("this is how it's done")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.