表现:使用动态示例编写场景大纲

时间:2017-01-10 10:11:22

标签: cucumber gherkin python-behave

Gherkin / Behave 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 |

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

enter image description here

我的问题

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

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

更新:在行为项目上打开github issue

3 个答案:

答案 0 :(得分:2)

我想出了另一个解决方案(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

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

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 对象大惊小怪,我只是从表中复制并更新它。为了更加丑陋,如果您使用的是文件,您可以将文件名放在示例表中。

答案 1 :(得分:1)

到这里寻找其他东西,但由于我以前和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层。

答案 2 :(得分:-1)

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

好的,但更大的问题呢?您希望将方案大纲与不能放在要素文件中的示例一起使用。每当我遇到这个问题时,我所做的就是给出我需要的数据的描述,并让步骤实现创建用于测试的实际数据集或 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的值创建或获取适当类型的用户。