Testing Private Methods in Python (An Exception)
Python does some name mangling when it puts the actually-executed code together. Thus, if you have a private method __A
on MyClass
, you would need to run it like so in your unit test:
from unittest import TestCase
class TestMyClass(TestCase):
def test_private(self):
expected = 'myexpectedresult'
m = MyClass()
actual = m._MyClass__A
self.assertEqual(expected, actual)
The question came up about so-called 'protected' values that are demarcated by a single underscore. These method names are not mangled, and that can be shown simply enough:
from unittest import TestCase
class A:
def __a(self):
return "myexpectedresult"
def _b(self):
return "a different result"
class TestMyClass(TestCase):
def test_private(self):
expected = "myexpectedresult"
m = A()
actual = m._A__a()
self.assertEqual(expected, actual)
def test_protected(self):
expected = "a different result"
m = A()
actual = m._b()
self.assertEqual(expected, actual)
# actual = m._A__b() # Fails
# actual = m._A_b() # Fails
First of all, you CAN access the "private" stuff, can't you? (Or am I missing something here?)
>>> class MyClass(object):
... def __init__(self):
... pass
... def __A(self):
... print('Method __A()')
...
>>> a=MyClass()
>>> a
<__main__.MyClass object at 0x101d56b50>
>>> a._MyClass__A()
Method __A()
But you could always write a test function in MyClass
if you have to test the internal stuff:
class MyClass(object):
...
def _method_for_unit_testing(self):
self.__A()
assert <something>
self.__B()
assert <something>
....
Not the most elegant way to do it, to be sure, but it's only a few lines of code at the bottom of your class.