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)