Python 装饰器:在测试前运行装饰器

Posted

技术标签:

【中文标题】Python 装饰器:在测试前运行装饰器【英文标题】:Python decorator: run decorator before test 【发布时间】:2017-08-20 14:45:28 【问题描述】:

我希望添加一个在某些测试中运行录像机的装饰器,如下所示:

@decorators.video(self)
def test_1234(self):
    ...

我无法将 self 变量传递给装饰器,因为它需要一些属性。我该怎么做?

【问题讨论】:

如果你认为你需要这个,你在这里做的事情非常错了。请显示装饰器的代码。 在方法装饰器执行的时候,类还没有被创建,所以实例没有办法。然而,包装函数被调用时的第一个参数,因为它是包装方法的第一个参数,是实例self。您可以在调用时访问它,而不是在装饰时访问它。 【参考方案1】:

theodox 的答案通常很好,但对于装饰器,您应该使用 functools.wraps 函数,如下例所示:

from functools import wraps

def enable_video(fn)
    '''Decorate the function to start video, call the function, stop video.'''
    @wraps(fn)
    def inner(*args, **kwargs): 
    # could be just `def inner(self):` if only intended to use
    # with methods without arguments and keyword arguments
        do_stuff_before()
        fn(*args, **kwargs)
        do_stuff_after()
    return inner

它将保留原始文档字符串、原始函数名称(等等)。您可以在Python docs 阅读更多相关信息。

那么,假设前面的代码在decorators模块中,你应该如下使用它:

class MyTestCase(unittests.TestCase);
    @decorators.enable_video
    def testSomeVideoFunction(self):
        do_test_stuff()

请注意,在代码示例中,它只是 @decorators.enable_video不是 @decorators.enable_video(self)。就像 jonrsharpe 对您的问题的评论一样,在装饰时不存在对 self 的引用。

【讨论】:

【参考方案2】:

您确定需要self 引用吗?

通常你会做这样的事情

def enable_video(fn):
    '''decorate the test function so it starts the video, runs the test, and stop the video'''   
    def video_aware_test(self_refrence):
       start_video_recorder()
       try:
          fn()
       finally:
          stop_video_recorder()
    return video_aware_test

你会这样应用它:

 @enable_video
 def test_something(self)

如果出于某种原因装饰器确实需要自引用,您可以查看在哪里获取它。此版本不包括以任何方式配置视频记录器,您将使用类而不是函数装饰器并将配置作为参数传递。

【讨论】:

以上是关于Python 装饰器:在测试前运行装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python3+selenium-unittest之装饰器(@classmethod)

python装饰器

python装饰器

Python:如何在单元(鼻子)测试期间忽略装饰器?

Selenium2+python自动化55-unittest之装饰器(@classmethod)

python自动测试Pytest中Fixture装饰器