总是执行带参数的测试装饰器

Test decorators with arguments are always executed

我想要实现的是将某些测试所需的设置代码放入装饰器函数中。我 故意避免 setUptearDown 方法,因为它们由测试用例中的所有测试共享,而这不是我要找的。这更多的是个人喜好和学习兴趣的问题,而不是寻求直接的解决方案。

代码的简化版本:

# some import lines
from some.package import interceptor

class TestWhatever(unittest.TestCase):

    def test_simple_thing(self):
        # simple stuff

    def test_another_simple_thing(self):
        # more simple stuff

    @interceptor(arg1, arg2)
    def test_with_some_preparation_needed(self):
        # hey! Really cool stuff in here

    print('This will be executed with every test')

    @interceptor(arg1, arg2, namedarg1='foo', namedarg2='bar')
    def test_with_preparation_also(self):
        # the first decorator is executed
        # sure I'm not following Python's Zen

装饰函数:

from wsgi_intercept import requests_intercept
from wsgi_intercept import add_wsgi_intercept


def interceptor(cityname, response, host='localhost', port=8000):
    requests_intercept.install()
    add_wsgi_intercept(host, port,
                       lambda: create_webservice(cityname, response))

    def decorator(test):

        def runtest(self):
            test(self)
            requests_intercept.uninstall()

        return runtest

    return decorator


def create_webservice(cityname, response):

    def app(environ, start_response):
        # a simple WSGI app

    return app

每个装饰器都是一个带参数的函数调用,因为我需要对设置进行参数化。调用 returns 测试的真正装饰器。问题是它们就像放置在函数定义之间的任何其他语句一样,因此它们会被执行。

像我这样用参数测试装饰器的想法可行吗?也许有了数据提供商,这将成为可能。

将每个测试要执行的所有内容移动到runtest包装器中。 interceptor() 装饰器工厂和 decorator 本身都会在 创建 TestWhatever class 对象时执行 :

def interceptor(cityname, response, host='localhost', port=8000):    
    def decorator(test):
        def runtest(self):
            requests_intercept.install()
            add_wsgi_intercept(
                host, port,
                lambda: create_webservice(cityname, response))
            test(self)
            requests_intercept.uninstall()
        return runtest    
    return decorator

注意,normal模式仍然使用setUptearDown,并且只使用那些需要在 class 中进行特定设置的测试。您可以随时添加更多 TestCase classes 而无需为其他测试设置:

class TestWhateverWithSetup(unittest.TestCase):
    def setUp(self):
        requests_intercept.install()
        add_wsgi_intercept(
            host, port,
            lambda: create_webservice(cityname, response))

    def tearDown(self):
        requests_intercept.uninstall()

    def test_with_some_preparation_needed(self):
        # hey! Really cool stuff in here

    def test_with_preparation_also(self):
        # the first decorator is executed
        # sure I'm not following Python's Zen


class TestWhateverWithoutSetup(unittest.TestCase):
    def test_simple_thing(self):
        # simple stuff

    def test_another_simple_thing(self):
        # more simple stuff