How to dynamically add tests in python unittest

I want to set up an immodest TestCase where some of them are added dynamically. Methods are added, as shown in my tests, but unittest does not take them into account, since it runs only one test, since I create my test_xxxx too late and is not taken into account. Does setUpClass run at the end of the game? Should I put this in __init__ build my methods and then call super().__init__ ?

 import unittest import blognodes class Test_base62(unittest.TestCase): testset = { 0: '0', 10: 'a', 61: 'Z', 62: '10', 3844: '100'} @classmethod def setUpClass(cls): cls.testme = 5 print("i am the setUp function") for d, b62 in cls.testset.items(): print("building the first set") cls.build_test_base62_values(d, b62) print("building the second set") cls.build_test_int_values(d, b62) @classmethod def build_test_base62_values(cls, d, b62): def f(cls): target = blognodes.base62(d) cls.assertEqual(target.str(), b62) fname = "test_base62_value_{}".format(d) setattr(cls, fname, f) @classmethod def build_test_int_values(cls, d, b62): def f(cls): target = blognodes.base62(d) cls.assertEqual(target.int(), d) fname = "test_int_value_{}".format(d) setattr(cls, fname, f) def test_nothing(self): print("i'm test nothing") t = dir(self) print(t) self.assertEqual(5, self.testme) 

Thanks.

+4
source share
1 answer

The problem is that the loader from unittest runs the dir () class in the class before it is created, so it doesn't matter where you create your methods, __new__ , __init__ , setUpClass , etc ... methods are created too late.

There are two ways around this, write your own run () method, or use a metaclass. The first means that you need to re-write the discovery that is already written in unittest. The metaclass is actually not that hard to implement. Here is what I did:

 import unittest import blognodes class meta_Test_base62(type): testset = { 0: '0', 10: 'a', 61: 'Z', 62: '10', 3844: '100'} @classmethod def __prepare__(mcls, name, bases): d = dict() d['testme'] = 5 for b10, b62 in mcls.testset.items(): fname = "test_base62_value_{}".format(b10) d[fname] = mcls.build_test_base62_values(b10, b62) fname = "test_int_value_{}".format(b10) d[fname] = mcls.build_test_int_values(b10, b62) return d @classmethod def build_test_base62_values(cls, b10, b62): def f(self): target = blognodes.base62(b10) self.assertEqual(target.str(), b62) return f @classmethod def build_test_int_values(cls, b10, b62): def f(self): target = blognodes.base62(b10) self.assertEqual(target.int(), b10) return f class Test_base62(unittest.TestCase, metaclass=meta_Test_base62): def test_nothing(self): self.assertEqual(5, self.testme) 
+4
source

Source: https://habr.com/ru/post/1413655/


All Articles