绑定到不同的方法

时间:2014-09-16 05:25:52

标签: python

我使用以下函数将测试添加到我的测试用例中。

def add_tests(cls, args, name_builder):
   for a in args:
      def tb(a):
         return lambda self: self.test_body(*a)
      setattr(cls, name_builder(a), tb(a))

目前我可以像这样使用它:

class TestEqual(unittest.TestCase):
   def test_body(self, i, j):
      self.assertNotEquals(0, i-j)

add_tests(TestEqual, ((0,0),(1,1)), build_name_1)

如何更改add_tests以执行以下操作:

class TestRestart(unittest.TestCase):

   def test_mode_flow(self, mode):
       machine.set_mode(mode)
       self.assertTrue(machine.restart())

   def test_gear_flow(self, gear, speed):
       machine.set_gear(gear)
       machine.set_speed(speed)
       self.assertTrue(machine.restart())

add_tests(TestRestart, test_mode_flow, (mode.SILENT, mode.NOISY), build_name_mode)
add_tests(TestRestart, test_gear_flow, ((1,33),(4,22)), build_name_gear)

换句话说,我想删除对self.test_body(*a)的硬编码调用,而是将选择的方法作为参数传递。

1 个答案:

答案 0 :(得分:1)

您可以将方法的名称传递给add_tests函数:

def add_tests(cls, method_name, name_builder, *args):
    method = getattr(cls, method_name)
    for arg in args:
        setattr(cls, name_builder(arg), lambda self, arg=arg: method(*arg))

用作:

class TestRestart(unittest.TestCase):
    def test_mode_flow(self, mode):
        machine.set_mode(mode)
        self.assertTrue(machine.restart())

    def test_gear_flow(self, gear, speed):
        machine.set_gear(gear)
        machine.set_speed(speed)
        self.assertTrue(machine.restart())

add_tests(TestRestart, 'test_mode_flow', build_name_mode, mode.SILENT, mode.NOISY)
add_tests(TestRestart, 'test_gear_flow', build_name_gear, (1,33), (4,22))

另一种方法是直接传递方法:

def add_tests(cls, method, name_builder, *args):
    for arg in args:
        setattr(cls, name_builder(arg), lambda self, arg=arg: method(self, *arg))

并将其用作:

add_tests(TestRestart, TestRestart.test_mode_flow, build_name_mode, mode.SILENT, mode.NOISY)
add_tests(TestRestart, TestRestart.test_gear_flow, build_name_gear, (1,33), (4,22))

另一种选择是使用装饰器:

from functools import wraps

def add_tests(*args):
    def decorator(method):
        @wraps(method)
        def wrapper(self):
            for arg in args:
                method(self, *arg)
        return wrapper
    return decorator

并将其用作:

class TestRestart(unittest.TestCase):
    @add_tests(mode.SILENT, mode.NOISY)
    def test_mode_flow(self, mode):
        machine.set_mode(mode)
        self.assertTrue(machine.restart())

    @add_tests((1, 33), (4, 22))
    def test_gear_flow(self, gear, speed):
        machine.set_gear(gear)
        machine.set_speed(speed)
        self.assertTrue(machine.restart())

但是,这会将所有测试打包到一个方法中,这可能不是您想要的。 但是,可以修改add_tests,以便错误消息显示哪个参数失败,从而提供相同级别的信息。