【问题标题】:BDD behave Python need to create a World map to hold valuesBDD 行为 Python 需要创建一个世界地图来保存值
【发布时间】:2017-03-19 17:30:59
【问题描述】:

我对 Python 不太熟悉,但我已经使用 Python 行为设置了一个 BDD 框架,我现在想创建一个世界地图类来保存数据并且在所有场景中都可以检索。

例如,我将有一个世界级的我可以使用:

World w 

w.key.add('key', api.response)

在一种情况下,在另一种情况下,我可以使用:

World w

key = w.key.get('key'). 

编辑:

或者,如果有一种使用上下文或类似行为的内置方式,其中属性在所有场景中都可以保存和检索,这将是很好的。

像生菜一样,你可以使用世界http://lettuce.it/tutorial/simple.html

我已经在不同场景之间尝试过,但似乎没有成功

class World(dict):
    def __setitem__(self, key, item):
        self.__dict__[key] = item
        print(item)

    def __getitem__(self, key):
        return self.__dict__[key]

场景A中一步设置item:w.setitem('key', response)

在场景 B 的另一个步骤中获取项目:w.getitem('key',)

这向我显示了一个错误:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python\lib\site-packages\behave\model.py", line 1456, in run
    match.run(runner.context)
  File "C:\Program Files (x86)\Python\lib\site-packages\behave\model.py", line 1903, in run
    self.func(context, *args, **kwargs)
  File "steps\get_account.py", line 14, in step_impl
    print(w.__getitem__('appToken'))
  File "C:Project\steps\world.py", line 8, in __getitem__
    return self.__dict__[key]
KeyError: 'key'

世界似乎在运行的步骤之间不保存值。

编辑:

我不确定如何使用 environment.py,但可以看到它有一种在步骤之前运行代码的方式。如何允许调用 environment.py 中的肥皂客户端,然后将其传递给特定步骤?

编辑:

我已经在 environment.py 中提出了请求并对值进行了硬编码,如何将变量传递给 environment.py 并返回?

【问题讨论】:

    标签: python bdd suds python-behave


    【解决方案1】:

    在 python 行为行话中称为“上下文”。你的步骤定义函数的第一个参数是一个behavior.runner.Context 类的实例,你可以在其中存储你的世界实例。请看the appropriate part of the tutorial.

    【讨论】:

    • 我试过这个,但它没有在我需要的场景之间共享上下文。因为我使用的是肥皂客户端,所以我需要拿到下一个场景的钥匙
    • 是的,没错,为每个场景重新创建上下文,以尽量减少场景之间可能的干扰。您不能依赖于您的场景的任何执行顺序。如果您真的坚持在场景之间共享数据,您可以将数据保存在磁盘上并从那里重新读取,但您的下一个问题很可能是您的场景有时会以意想不到的顺序执行。您应该以一种在每个需要它的场景中获取一个新密钥的方式来构建您的场景。使用标签+beforescenario 或专用步骤定义。
    • 有没有办法调用soap客户端并检索令牌并将其传递给environment.py中的特定步骤?
    • 不要直接调用 environment.py 的方法。您可以按照 stovfl 的建议定义 before_all 和 before_scenario 挂钩。至于何时请求肥皂令牌,完全取决于您。如果您将其保存在全局变量中,您可以在所有场景的整个测试运行中使用相同的令牌,或者您可以为每个场景重新请求 if 并将其存储在上下文中,您也可以为每个场景重新请求它一个请求,只要你需要它。这真的取决于您的需求。
    【解决方案2】:

    你试过了吗 简单的方法,例如使用global var

    def before_all(context):
        global response
        response = api.response
    
    def before_scenario(context, scenario):
        global response
        w.key.add('key', response)
    

    猜测feature可以从context访问,例如:

    def before_feature(context, feature):
        feature.response = api.response
    
    def before_scenario(context, scenario):
        w.key.add('key', context.feature.response)
    

    您正在寻找:
    类变量:由类的所有实例共享的变量。
    您在 Q 中的代码使用类实例变量
    阅读:python_classes_objects

    例如:

    class World(dict):
        __class_var = {}
    
        def __setitem__(self, key, item):
            World.__class_var[key] = item
    
        def __getitem__(self, key):
            return World.__class_var[key]
    
    # Scenario A
    A = World()
    A['key'] = 'test'
    print('A[\'key\']=%s' % A['key'] )
    del A
    
    # Scenario B
    B = World()
    print('B[\'key\']=%s' % B['key'] )
    

    输出

    A['key']=test
    B['key']=test  
    

    用 Python:3.4.2 测试
    如果这对您有用,请返回并将您的问题标记为已回答,或评论为什么不这样做。

    【讨论】:

    • 这不起作用,因为测试的顺序没有按正确的顺序运行。我已将此添加到 environment.py 但需要知道如何将变量传递给它
    • @stovi 感谢您的帮助,但我真正希望它能够将 BDD 步骤中的 class.py 文件中的变量传递给项目文件夹位置中的 environment.py .然后使用这些变量发出请求。然后将响应传回给 class.py。你能帮我解决这个问题吗?
    • @Samantha:你尝试过def before_... 的任何提议吗?
    【解决方案3】:

    在 before_all 钩子中定义 global var 对我不起作用。 正如@stovfl 所提到的

    但是在我的一个步骤中定义全局变量成功了。

    相反,正如 Szabo Peter 提到的那样,使用上下文。

    context.your_variable_name = api.response 并使用 context.your_variable_name 任何要使用该值的地方。

    【讨论】:

      【解决方案4】:

      为此,我实际上使用了一个配置文件 [config.py],然后我在其中添加了变量并使用 getattr 检索它们。见下文:

      WSDL_URL = 'wsdl'
      USERNAME = 'name'
      PASSWORD = 'PWD'
      

      然后像这样检索它们:

      import config
      
      getattr(config, 'USERNAME ', 'username not found')
      

      【讨论】:

      • 这可能是针对您的特定情况的有效解决方案,但不能回答您自己关于如何在场景之间共享数据的问题。 Stovfl 的回答对这个问题有最好的建议,使用全局变量。
      • 这不是真的,因为我还可以修改配置中的值并轻松检索它们。对我来说,这比使用全局变量更容易
      • 最大的不同是你的步骤定义不能像修改全局变量那样容易地修改 config.py。当然,在您的情况下,您不需要修改它,这就是为什么它是在场景之间共享数据的特殊情况,而不是原始问题的内容,即在一个场景中写入世界级的实例并读取令牌回到另一个。
      • 所以他们不能用 setattr 修改配置?
      • 其实你是对的,你可以,在记忆中。它不会被持久化。我希望能够删除场景之间的导入,但它没有,我只是尝试过。哦,你可以简单地使用 config.USERNAME 而不是 getattr 和 setattr。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 2017-04-01
      • 2021-11-02
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      相关资源
      最近更新 更多