我目前正在使用Behave(BDD for Python),并且一直在挖掘源代码,以了解如何声明@given
,@when
和@then
装饰器。
我离开的最远的地方是查看step_registry.py
我找到了正在执行此项工作的setup_step_decorators(context=None, registry=registry)
函数。
但是,我不太明白这些装饰器是如何创建的,因为它们似乎没有以def when(...):
的形式在源代码中显式声明。我的印象是,它们是根据字符串列表(for step_type in ('given', 'when', 'then', 'step'):
)声明的,然后通过调用make_decorator()
进行处理。
有人可以引导我完成代码并解释这些装饰器在何处/如何宣布?
您可以在此处访问source code of Behave。
答案 0 :(得分:4)
好吧,让我们从外面开始:
if context is None:
context = globals()
for step_type in ('given', 'when', 'then', 'step'):
step_decorator = registry.make_decorator(step_type)
context[step_type.title()] = context[step_type] = step_decorator
我认为这是困扰你的最后一行。
每个模块的全局命名空间只是一个字典。函数globals()
返回该字典。如果修改该字典,则创建新的模块全局变量。例如:
>>> globals()['a'] = 2
>>> a
2
在这种情况下,默认情况下为context = globals()
。所以,对于第一个step_type
来说,你有效地做到了这一点:
>>> globals()['given'] = step_decorator
答案 1 :(得分:3)
它们被注入第90行的globals()
(此时context
为globals()
,因为context
为None
):
# -- Create the decorators
def setup_step_decorators(context=None, registry=registry):
if context is None:
context = globals()
for step_type in ('given', 'when', 'then', 'step'):
step_decorator = registry.make_decorator(step_type)
context[step_type.title()] = context[step_type] = step_decorator
您也可以自己这样做(globals()
就像普通字典一样):
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> globals()['a'] = 5
>>> a
5