This answer explains how to create test cases dynamically.
The answer’s code:
class Tests(unittest.TestCase):
def check(self, i, j):
self.assertNotEquals(0, i-j)
for i in xrange(1, 4):
for j in xrange(2, 6):
def ch(i, j):
return lambda self: self.check(i, j)
setattr(Tests, "test_%r_%r" % (i, j), ch(i, j))
I’ve tested and it works, but I can’t just figure out how?
I have trouble understanding the lambda self: magic in play here, mainly:
- Is the lambda used here to perform the exact opposite of
functools.partial()(i.e. to create a wrapper function with one extra parameter that is not yet known) - Is
selfa meaningful keyword or wouldlambda spamwould work just as well? - What point is that lambda evaluated?
- How come the
.check()is perfectly fine outside theclasses scope? - How do you do this without lambda? – if I understand correctly, you should be able to do without
lambda(not to mention that I agree with Guido and Alex that it is an eyesore and I want to do without 🙂
First of all: The lambda is returned from a function to prevent that modified values of
iandjwill be used later.Compare to the following:
This will not work as expected, as all the lambdas will share the same namespace and will use the values of
iandjafter the end of the loop. If we use a separate function call, we introduce a new closure every time that captures the values ofiandjat the point in time where the function is called.We could achieve the same by saving the current values of
iandjas default arguments of the lambda. For good measure, let’s also useitertools.productto avoid the nested loop:Not really. It just calls the
check(i, j)method on whatever it is given as an argument. This is used here to dynamically add methods to theTestsclass.spamwould work just as well. They chooseselfhere due to convention because the lambda represents a method.As soon as
test_[i]_[j]()is called on an instance ofTests.Because it’s inside a lambda will only be called later with an instance of
Testsas theselfargument.