I periodically find myself attempting to slightly abuse some of the dinamicity allowed by python (I'm using python3 here, but there shouldn't be many differences).
In this case, I wanted to split a single test_ method in my unittest.TestCase
, to several methods created at runtime.
(this was a Kata about roman numerals, but I actually didn't TDD: I wrote the test later)
This is the test:
class TestNumbers(TestCase):
def test_number(self):
for i in range(3000):
self.assertEqual(i, roman_to_int(int_to_roman(i)))
this is how I tried to write it:
from functools import partial
from types import MethodType
class TestNumbers(TestCase):
pass
def test_number(self, n):
self.assertEqual(n, roman_to_int(int_to_roman(n)))
for i in range(3000):
name = str(i)
test_method = MethodType(partial(test_number, n=i), TestNumbers)
setattr(TestNumbers, "test" + name, test_method)
(alternatively, I also tried to dinamically create lots of TestCase subclasses and setattr(globals(), ...)
them)
I know: this doesn't really has much purpose, it's also probably slower, etc.etc. but this is just a POC and I'm trying to understand how I can get it to work
by using MethodType, the test becomes a bound method, but inside, assertEqual apparently becomes a function, and when trying to call it it'll fail with TypeError: assertEqual() takes at least 3 arguments (2 given)
I tried to change test_number to
def test_number(self, n):
self.assertEqual(self, n, roman_to_int(int_to_roman(n)))
but this will only unearth the same problem deeper in hidden TestCase methods: TypeError: _getAssertEqualityFunc() takes exactly 3 arguments (2 given)
I looked here on stackoverflow and found similar questions (like Python: Bind an Unbound Method? ), but none of those deal with binding a method that inside of it calls other bound methods of the target class
I also tried to look into metaclasses ( http://docs.python.org/py3k/reference/datamodel.html#customizing-class-creation ) but it doesn't seem to match with what I'm trying to do