如何创建/声明行为的装饰器?



我目前正在使用Behave (Python的BDD),并一直在源代码中挖掘,以了解如何声明@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()来处理。

谁能告诉我代码和解释在哪里/如何声明这些装饰符?

让我们从外部开始:

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

它们在第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

最新更新