Reputation: 3759
In python 2.7, is it possible to test module privates?
After running:
import unittest
__private_stuff = 1 # if it would have single underscore, it would not be a problem.
class ComplexTestCase(unittest.TestCase):
def test_internal_symbol(self):
self.assertEqual(__private_stuff, 1)
unittest.main(__name__)
Result is:
E
======================================================================
ERROR: test_internal_symbol (__main__.ComplexTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\files\y.py", line 7, in test_internal_symbol
self.assertEqual(__private_stuff, 1)
NameError: global name '_ComplexTestCase__private_stuff' is not defined
----------------------------------------------------------------------
Is there any way arround it?
(without modifying the code to which I want to add tests)
One way would be to just rename the methods.
Other way would be to add additional renamed symbol private_stuff = __private_stuff
.
But this becomes very tedious quickly.
Codebase uses these '__xyz' as public symbols (uses from other modules) and there is quite a lot of them.
Also there always exists '_xyz' and 'xyz' symbols.
(Trying to find the answer of "why", figured the only reasonable explanation
is that leading underscores was used to mark "modified" as in mathematical formulas "prime" is used.
e.g. x
and x'
are similar, but not the same)
Upvotes: 0
Views: 410
Reputation: 40778
There are a few ways you could prevent python invoking the name mangling algorithm in your class
Use getattr
to retrieve the value of the attribute under test (as per 1.618's answer):
class ComplexTestCase(unittest.TestCase):
def test_internal_symbol(self):
private_stuff = getattr(module_under_test, '__private_stuff')
self.assertEqual(private_stuff, 1)
Write the test method outside of a class:
def test_internal_symbol(self):
self.assertEqual(module_under_test.__private_stuff, 1)
class ComplexTestCase(unittest.TestCase):
test_internal_symbol = test_internal_symbol
Refactor the private attributes names to end with 3 underscores:
class ComplexTestCase(unittest.TestCase):
def test_internal_symbol(self):
self.assertEqual(module_under_test.__private_stuff___, 1)
Upvotes: 0
Reputation: 1765
Where is __private_stuff
actually defined? Because I doubt it's defined in your test case module. If it really is, then this will work:
import unittest
__private_stuff = 1 # if it would have single underscore, it would bot be a problem.
class ComplexTestCase(unittest.TestCase):
def test_internal_symbol(self):
private_stuff = globals()['__private_stuff']
self.assertEqual(private_stuff, 1)
unittest.main(__name__)
Otherwise, if it's in some other module, this should work, although I didn't test it:
import unittest
import other_module
__private_stuff = 1 # if it would have single underscore, it would bot be a problem.
class ComplexTestCase(unittest.TestCase):
def test_internal_symbol(self):
private_stuff = getattr(other_module, '__private_stuff')
self.assertEqual(private_stuff, 1)
unittest.main(__name__)
Upvotes: 3