Behave的装饰器是如何创建/声明的?

时间:2014-08-08 22:57:50

标签: python bdd python-decorators python-behave

我目前正在使用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

2 个答案:

答案 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()(此时contextglobals(),因为contextNone):

# -- 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