Home > other >  How to dynamically load a function to test unit with exec()?
How to dynamically load a function to test unit with exec()?

Time:02-06

I want to load the function into the unit test dynamically, passing code as str and use exec() to run them in test.

My current code look like this:

import unittest

class ParametrizedTestCase(unittest.TestCase):
    def __init__(self, methodName='runTest', param=None):
        super(ParametrizedTestCase, self).__init__(methodName)
        exec (param)
        self.param = param

    @staticmethod
    def parametrize(testcase_klass, param=None):
        testloader = unittest.TestLoader()
        testname = testloader.getTestCaseNames(testcase_klass)
        suite = unittest.TestSuite()
        for name in testname:
            suite.addTest(testcase_klass(name, param=param))
        return suite

class TestZero(ParametrizedTestCase):
    def test_add(self):
        print('param:', self.param)
        self.assertEqual(add(1,1), 2)

if __name__ == '__main__':
    code = "def add(a, b): return a   b"
    suite = ParametrizedTestCase.parametrize(TestZero, param=code)
    unittest.TextTestRunner(verbosity=2).run(suite)

and this is current out put:

❯ python test/test0.py
test_add (__main__.TestZero) ... param: def add(a, b): return a   b
ERROR

======================================================================
ERROR: test_add (__main__.TestZero)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/test0.py", line 21, in test_add
    self.assertEqual(add(1,1), 2)
NameError: name 'add' is not defined

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

Is it possible to do that and if so, how?

CodePudding user response:

exec with no additional parameters is defining add in the local scope of ParameterizedTestCase.__init__; once that function complete, add goes out of scope.

One solution is to put add in the global scope, so that it's accessible.

exec(param, globals())

However, in general you aren't going to know what name (or names) the execution of param will make available for future tests.

  •  Tags:  
  • Related