Py.test - 基于会话的设置

时间:2011-11-07 02:38:07

标签: python decorator pytest

我正在尝试围绕py.test建立一个不错的基础

我们的一些测试需要某些测试数据才能工作。

今天我们只是将模拟对象指定为函数参数并在生成器中进行设置,这显然是不可取的。

以下是今天的展示方式示例:

def test_something(self, some_data):
    # some_data is unused in the test

我想做这样的事情:

@uses_some_data
def test_something(self):
    # The data is loaded when the test is run

虽然我还没弄清楚如何正确地做到这一点。

我不能使用类设置,因为我希望数据在整个会话中保持不变,而不是在每个测试类上设置/拆除。

我的第一个想法是仍然使用funcargs但是我们让装饰器为函数请求funcarg,而不是让测试有funcarg,基本上隐藏了丑陋。

这个问题是我需要一个py.test对象来请求一个funcarg 有什么方法可以得到这样的对象,或者这是一起错误的方法吗?

如果收集的测试都不需要数据,则不需要加载数据,这将是一个非常好的奖励,这是使用装饰器看到的缺点,因为无论是否运行测试,它们总是运行不

2 个答案:

答案 0 :(得分:1)

这是可以按原样运作的东西,如果没有,希望能指出你正确的方向。

class TestData(object):
    def __getattr__(self, name):
        if name not in ('data1', 'data2', 'data3'):
            raise AttributeError("TestData has no %s" % name)
        if name == 'data1':
            result = self._generate_data('data1')
            setattr(self.__class__, name, result)
        elif name == 'data2':
            result = self._generate_data('data2')
            setattr(self.__class__, name, result)
        elif name == 'data3':
            result = self._generate_data('data3')
            setattr(self.__class__, name, result)
        return result
    def _generate_data(self, data_name):
        return data_name * int(data_name[-1])

TestData类使用__getattr__方法根据需要生成数据,并将生成的日期保存回类(而不是实例!),数据保留以备将来使用

class uses_some_data(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        global test_data
        test_data = TestData()
        return self.func(*args, **kwargs)

一个简单的装饰器,用于设置test_data的全局名称绑定。实际上,这个版本的装饰器非常简单,可以很容易地用test_data = TestData()的模块级名称绑定替换。

@uses_some_data
def testing_test():
    print(test_data.data2)

测试功能。

如果您不喜欢test_data的全局级别,您可以更好地使用装饰器并将test_data分配给函数本身:

class uses_some_data(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        self.func.test_data = TestData()
        return self.func(*args, **kwargs)

在这种情况下,请确保您的测试功能自行引用

@uses_some_data
def testing_test():
    print(testing_test.test_data.data2)

答案 1 :(得分:1)

在玩了一些后,我发现这有效:

def pytest_funcarg__some_data(request):
    def create():
        # Load the test data here
        print 'Test data loaded'

    return request.cached_setup(
        setup=create,
        scope='session',
        extrakey='some_data'
    )

def uses_some_data(func):
    # The funcarg is actually requested here
    def wrapper(self, some_data):
        return func
    return wrapper

class TestSomething(object):
    @uses_some_data
    def test_something(self):
        # "Some data" is now available
        pass