【问题标题】:getting test class instance in nose test object to sync up with instance in decorated generator target在鼻子测试对象中获取测试类实例以与装饰生成器目标中的实例同步
【发布时间】:2012-09-13 22:40:06
【问题描述】:

我一直在研究一种方法,让测试从鼻子中的生成器生成,以具有针对正在测试的特定迭代定制的描述。只要我的生成器目标方法从不尝试从我的生成器类访问self,我就有一些工作。我看到我的所有生成器目标实例都有一个公共测试类实例,而鼻子正在为生成器的每个测试运行生成一个一次性的测试类实例。这导致setUp 在鼻子创建的每个测试实例上运行,但从未在生成器目标绑定到的实例上运行(当然,真正的问题是我看不到如何绑定鼻子创建的实例到生成器目标)。这是我用来试图弄清楚这一切的代码(是的,我知道装饰器作为可调用类可能会更好,但是鼻子,至少我拥有的版本 1.2.1,明确检查测试是否是函数或方法,因此可调用的类根本不会运行):

import inspect

def labelable_yielded_case(case):

    argspec = inspect.getargspec(case)
    if argspec.defaults is not None:
        defaults_list = [''] * (len(argspec.args) - len(argspec.defaults)) + argspec.defaults
    else:
        defaults_list = [''] * len(argspec.args)
    argument_defaults_list = zip(argspec.args, defaults_list)
    case_wrappers = []

    def add_description(wrapper_id, argument_dict):

        case_wrappers[wrapper_id].description = case.__doc__.format(**argument_dict)

    def case_factory(*factory_args, **factory_kwargs):

        def case_wrapper_wrapper():

            wrapper_id = len(case_wrappers)

            def case_wrapper(*args, **kwargs):

                args = factory_args + args
                argument_list = []
                for argument in argument_defaults_list:
                    argument_list.append(list(argument))
                for index, value in enumerate(args):
                    argument_list[index][1] = value
                argument_dict = dict(argument_list)
                argument_dict.update(factory_kwargs)
                argument_dict.update(kwargs)
                add_description(wrapper_id, argument_dict)
                return case(*args, **kwargs)

            case_wrappers.append(case_wrapper)
            case_wrapper.__name__ = case.__name__
            return case_wrapper

        return case_wrapper_wrapper()

    return case_factory


class TestTest(object):

    def __init__(self):

        self.data = None

    def setUp(self):

        print 'setup', self
        self.data = (1,2,3)

    def test_all(self):

        for index, value in enumerate((1,2,3)):
            yield self.validate_equality(), index, value

    def test_all_again(self):

        for index, value in enumerate((1,2,3)):
            yield self.validate_equality_again, index, value

    @labelable_yielded_case
    def validate_equality(self, index, value):
        '''element {index} equals {value}'''

        print 'test', self
        assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])

    def validate_equality_again(self, index, value):

        print 'test', self
        assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])

    validate_equality_again.description = 'again'

当通过鼻子运行时,again 测试工作得很好,但是使用修饰生成器目标的测试集都失败了,因为self.data is None(因为setUp 永远不会运行,因为TestTest 的实例存储在闭包不是鼻子运行的实例)。我尝试让装饰器成为TestTest 的基类的实例成员,但是鼻子抛出了关于传递给未绑定labelable_yielded_case 的参数太少(没有self)的错误。有什么办法可以使这项工作(没有砍头),还是我在不能让产量目标成为实例成员或没有为每个产量测试都贴上每个测试标签之间做出选择?

【问题讨论】:

    标签: python generator nose


    【解决方案1】:

    修复了它(至少对于这里的情况,尽管我认为我在所有情况下都得到了它)。我不得不摆弄case_wrapper_wrappercase_wrapper 以让工厂返回附加到正确类的包装案例,但不以任何方式绑定到任何给定实例。我还有另一个代码问题,因为我在包装器包装器中构建参数 dict,但没有将它传递给案例。工作代码:

    import inspect
    
    def labelable_yielded_case(case):
    
        argspec = inspect.getargspec(case)
        if argspec.defaults is not None:
            defaults_list = [''] * (len(argspec.args) - len(argspec.defaults)) + argspec.defaults
        else:
            defaults_list = [''] * len(argspec.args)
        argument_defaults_list = zip(argspec.args, defaults_list)
        case_wrappers = []
    
        def add_description(wrapper_id, argument_dict):
    
            case_wrappers[wrapper_id].description = case.__doc__.format(**argument_dict)
    
        def case_factory(*factory_args, **factory_kwargs):
    
            def case_wrapper_wrapper():
    
                wrapper_id = len(case_wrappers)
    
                def case_wrapper(*args, **kwargs):
    
                    argument_list = []
                    for argument in argument_defaults_list:
                        argument_list.append(list(argument))
                    for index, value in enumerate(args):
                        argument_list[index][1] = value
                    argument_dict = dict(argument_list)
                    argument_dict.update(kwargs)
                    add_description(wrapper_id, argument_dict)
                    return case(**argument_dict)
    
                case_wrappers.append(case_wrapper)
                case_name = case.__name__ + str(wrapper_id)
                case_wrapper.__name__ = case_name
                if factory_args:
                    setattr(factory_args[0].__class__, case_name, case_wrapper)
                    return getattr(factory_args[0].__class__, case_name)
                else:
                    return case_wrapper
    
            return case_wrapper_wrapper()
    
        return case_factory
    
    
    class TestTest(object):
    
        def __init__(self):
    
            self.data = None
    
        def setUp(self):
    
            self.data = (1,2,3)
    
        def test_all(self):
    
            for index, value in enumerate((1,2,3)):
                yield self.validate_equality(), index, value
    
        @labelable_yielded_case
        def validate_equality(self, index, value):
            '''element {index} equals {value}'''
    
            assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多