Cucumber 行为:用动态示例编写场景大纲 小黄瓜/行为示例

Cucumber 行为:用动态示例编写场景大纲 小黄瓜/行为示例,cucumber,gherkin,python-behave,Cucumber,Gherkin,Python Behave,小黄瓜语法特征: 功能:场景大纲(教程04) 场景概述:将Blender与 假设我把“”放在搅拌机里 当我打开搅拌机时 然后它应该转换为“” 例子:两栖动物 |事情|其他事情| |红树蛙泥| |苹果|苹果汁| 示例:消费电子产品 |事情|其他事情| |iPhone |有毒废物| |Galaxy Nexus |有毒废物| 测试套件将运行四次,每个示例一次,结果类似于: 我的问题 如何使用示例部分中的机密数据进行测试?例如,我想用用户ID或SSN号测试一个内部API,而不用将数据硬编码在功能文件

小黄瓜语法特征:

功能:场景大纲(教程04)
场景概述:将Blender与
假设我把“”放在搅拌机里
当我打开搅拌机时
然后它应该转换为“”
例子:两栖动物
|事情|其他事情|
|红树蛙泥|
|苹果|苹果汁|
示例:消费电子产品
|事情|其他事情|
|iPhone |有毒废物|
|Galaxy Nexus |有毒废物|
测试套件将运行四次,每个示例一次,结果类似于:

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

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


更新:在behave项目上打开了一个链接。

来这里是想找些别的东西,但是因为我以前和Cucumber的情况类似,也许有人也会在这个问题上找到一个可能的解决方案。我解决这个问题的方法是使用
BDD变量
,稍后我可以在运行时在
step\u定义中处理这些变量。在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

所以你所要做的就是有一个定义良好的层。

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

好的,但是更大的问题呢?您希望使用场景大纲,其中包含无法放入功能文件中的示例。每当我遇到这个问题时,我所做的就是描述我需要的数据,并让步骤实现创建用于测试的实际数据集或从现有测试数据库获取数据集

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  |
场景大纲:访问管理界面
给定一个管理员已登录的用户
然后用户会看到管理界面
示例:用户
|地位|能力|
|是|可以吗|
|不是|不能|

无需在功能文件中显示有关用户的任何详细信息。步骤实现负责创建或获取适当类型的用户,具体取决于
状态的值

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

我通过使用
before\u功能
为场景大纲动态创建了示例

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

诀窍是在
environment.py
中使用
before\u功能
,因为它已经将示例表解析为场景大纲,但还没有从大纲生成场景

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
对象,我只是从表中复制并更新它。更糟糕的是,如果您使用的是文件,可以将文件名放在示例表中。

此更改将影响小黄瓜语言本身。如果它只是为“behave”实现的,那么behave将开始使用一种小黄瓜方言,它与cucumber-ruby、cucumber-java、specflow以及谁知道还有什么当前使用的小黄瓜方言大不相同。您应该尝试使伪数据可能与您的代码一起使用,这些数据可以安全地存储在功能文件中。
from behave import step

@step('the {number:d} squared is {result:d}')
def step_impl(context, number, result):
    assert number*number == result
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)
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