【问题标题】:Behave: Writing a Scenario Outline with dynamic examples行为:使用动态示例编写场景大纲
【发布时间】:2017-01-10 10:11:22
【问题描述】:

小黄瓜/行为Examples

Gherkin 语法特性test automation using examples:

Feature: Scenario Outline (tutorial04)

  Scenario Outline: Use Blender with <thing>
    Given I put "<thing>" in a blender
    When I switch the blender on
    Then it should transform into "<other thing>"

    Examples: Amphibians
        | thing         | other thing |
        | Red Tree Frog | mush        |
        | apples        | apple juice |

    Examples: Consumer Electronics
        | thing         | other thing |
        | iPhone        | toxic waste |
        | Galaxy Nexus  | toxic waste |

测试套件将运行四次,每个示例运行一次,结果类似于:

我的问题

如何使用Examples 部分中的机密数据进行测试?例如,我想使用用户 ID 或 SSN 号测试内部 API,而不将数据硬编码在功能文件中。

有没有办法从外部源动态加载Examples

更新:behave项目上打开了github issue

【问题讨论】:

  • 此更改将影响 Gherkin 语言本身。如果仅针对“行为”实现它,那么行为将开始使用小黄瓜方言,该方言与黄瓜红宝石、黄瓜Java、specflow目前使用的小黄瓜大不相同,谁知道还有什么。您应该尝试使虚假数据可以与您的代码一起使用,这些数据可以安全地存储在功能文件中。

标签: cucumber gherkin python-behave


【解决方案1】:

我想出了另一个解决方案(behave-1.2.6):

我设法使用before_feature 为场景大纲动态创建示例。

给定一个功能文件 (x.feature):

Feature: Verify squared numbers

  Scenario Outline: Verify square for <number>
    Then the <number> squared is <result>

Examples: Static
  | number | result |
  |   1    |    1   | 
  |   2    |    4   |
  |   3    |    9   |
  |   4    |   16   |

  # Use the tag to mark this outline
  @dynamic
  Scenario Outline: Verify square for <number>
    Then the <number> squared is <result>

Examples: Dynamic
  | number | result |
  |   .    |    .   | 

还有步骤文件(steps/x.step):

from behave import step

@step('the {number:d} squared is {result:d}')
def step_impl(context, number, result):
    assert number*number == result

诀窍是在environment.py 中使用before_feature,因为它已经将示例表解析为场景大纲,但尚未从大纲生成场景。

import behave
import copy

def before_feature(context, feature):
    features = (s for s in feature.scenarios if type(s) == behave.model.ScenarioOutline and
                'dynamic' in s.tags)
    for s in features:
        for e in s.examples:
            orig = copy.deepcopy(e.table.rows[0])
            e.table.rows = []
            for num in range(1,5):
                n = copy.deepcopy(orig)
                # This relies on knowing that the table has two rows.
                n.cells = ['{}'.format(num), '{}'.format(num*num)]
                e.table.rows.append(n)

这仅适用于带有@dynamic 标记的场景大纲。

结果是:

behave -k --no-capture
Feature: Verify squared numbers # features/x.feature:1

  Scenario Outline: Verify square for 1 -- @1.1 Static  # features/x.feature:8
    Then the 1 squared is 1                             # features/steps/x.py:3

  Scenario Outline: Verify square for 2 -- @1.2 Static  # features/x.feature:9
    Then the 2 squared is 4                             # features/steps/x.py:3

  Scenario Outline: Verify square for 3 -- @1.3 Static  # features/x.feature:10
    Then the 3 squared is 9                             # features/steps/x.py:3

  Scenario Outline: Verify square for 4 -- @1.4 Static  # features/x.feature:11
    Then the 4 squared is 16                            # features/steps/x.py:3

  @dynamic
  Scenario Outline: Verify square for 1 -- @1.1 Dynamic  # features/x.feature:19
    Then the 1 squared is 1                              # features/steps/x.py:3

  @dynamic
  Scenario Outline: Verify square for 2 -- @1.2 Dynamic  # features/x.feature:19
    Then the 2 squared is 4                              # features/steps/x.py:3

  @dynamic
  Scenario Outline: Verify square for 3 -- @1.3 Dynamic  # features/x.feature:19
    Then the 3 squared is 9                              # features/steps/x.py:3

  @dynamic
  Scenario Outline: Verify square for 4 -- @1.4 Dynamic  # features/x.feature:19
    Then the 4 squared is 16                             # features/steps/x.py:3

1 feature passed, 0 failed, 0 skipped
8 scenarios passed, 0 failed, 0 skipped
8 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.005s

这依赖于将具有正确形状的示例表作为最终表,在我的示例中,有两行。我也不大惊小怪地创建新的behave.model.Row 对象,我只是从表中复制一个并更新它。为了更加丑陋,如果您使用的是文件,则可以将文件名放在示例表中。

【讨论】:

    【解决方案2】:

    来到这里寻找其他东西,但由于我以前和 Cucumber 有过类似的情况,也许有人也会最终解决这个问题,寻找可能的解决方案。我解决这个问题的方法是使用BDD variables,稍后我可以在运行时在我的step_definitions 中处理它。在我的 python 代码中,我可以检查 Gherkin 变量的值并将其映射到需要的值。

    对于这个例子:

    Scenario Outline: Use Blender with <thing>
         Given I put "<thing>" in a blender
         When I switch the blender on
         Then it should transform into "<other thing>"
    
        Examples: Amphibians
            | thing         | other thing            |
            | Red Tree Frog | mush                   |
            | iPhone        | data.iPhone.secret_key | # can use .yaml syntax here as well
    

    会翻译成这样的 step_def 代码:

    @given('I put "{thing}" in a blender')
    def step_then_should_transform_into(context, other_thing):   
      if other_thing == BddVariablesEnum.SECRET_KEY: 
        basic_actions.load_secrets(context, key)
    

    所以你所要做的就是定义好DSL层。

    【讨论】:

      【解决方案3】:

      关于在测试中使用 SSN 号码的问题,我只是 use fake SSNs 而不担心我会泄露人们的私人信息。

      好的,但是更大的问题呢?您想使用场景大纲和无法放入功能文件的示例。每当我遇到这个问题时,我所做的就是描述我需要的数据,并让步骤实现 create 用于测试的实际数据集或 fetch 来自现有测试数据库的数据集。

      Scenario Outline: Accessing the admin interface
        Given a user who <status> an admin has logged in
        Then the user <ability> see the admin interface
      
      Examples: Users
        | status | ability |
        | is     | can     |
        | is not | cannot  |
      

      无需在功能文件中显示有关用户的任何详细信息。步骤实现负责根据status 的值创建或获取适当类型的用户。

      【讨论】:

        猜你喜欢
        • 2021-09-01
        • 1970-01-01
        • 2014-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多