TranslateProject/translated/tech/20180528 What is behavior-driven Python.md
2018-09-28 01:40:48 +08:00

12 KiB
Raw Blame History

什么是行为驱动的Python

您是否听说过行为驱动开发BDD并想知道所有的新奇事物是什么 也许你已经发现了团队成员在使用“gherkin”了并感到被排除在外无法参与其中。 或许你是一个Python爱好者正在寻找更好的方法来测试你的代码。 无论在什么情况下了解BDD都可以帮助您和您的团队实现更好的协作和测试自动化而Python的行为框架是一个很好的起点。

什么是BDD

  • 在网站上提交表单
  • 搜索想要的结果
  • 保存文档
  • 进行REST API调用
  • 运行命令行界面命令

在软件中,行为是指在明确定义的输入,行为和结果场景中功能是如何运转的。 产品可以表现出无数的行为,例如:

根据产品的行为定义产品的功能可以更容易地描述产品,并对其进行开发和测试。 BDD的核心是使行为成为软件开发的焦点。 在开发早期使用示例语言的规范来定义行为。 最常见的行为规范语言之一是GherkinCucumber项目中的Given-When-Then场景格式。 行为规范基本上是对行为如何工作的简单语言描述,具有一致性和焦点的一些正式结构。 通过将步骤文本“粘合”到代码实现,测试框架可以轻松地自动化这些行为规范。

下面是用Gherkin编写的行为规范的示例

根据产品的行为定义产品的功能可以更容易地描述产品,开发产品并对其进行测试。 这是BDD的核心使行为成为软件开发的焦点。 在开发早期使用示例规范的语言来定义行为。 最常见的行为规范语言之一是GherkinCucumber项目中的Given-When-Then场景格式。 行为规范基本上是对行为如何工作的简单语言描述,具有一致性和焦点的一些正式结构。 通过将步骤文本“粘合”到代码实现,测试框架可以轻松地自动化这些行为规范。

下面是用Gherkin编写的行为规范的示例

Scenario: Basic DuckDuckGo Search
  Given the DuckDuckGo home page is displayed
  When the user searches for "panda"
  Then results are shown for "panda"

快速浏览一下,行为是直观易懂的。 除少数关键字外,该语言为自由格式。 场景简洁而有意义。 一个真实的例子说明了这种行为。 步骤以声明的方式表明应该发生什么——而不会陷入如何如何的细节中。

BDD的主要优点是良好的协作和自动化。 每个人都可以为行为开发做出贡献,而不仅仅是程序员。 从流程开始就定义并理解预期的行为。 测试可以与它们涵盖的功能一起自动化。 每个测试都包含一个单一的,独特的行为,以避免重复。 最后,现有的步骤可以通过新的行为规范重用,从而产生雪球效果。

Python的behave框架

behave是Python中最流行的BDD框架之一。 它与其他基于Gherkin的Cucumber框架非常相似尽管没有得到官方的Cucumber定名。 behave有两个主要层:

  1. 用Gherkin的.feature文件编写的行为规范
  2. 用Python模块编写的步骤定义和钩子用于实现Gherkin步骤

如上例所示Gherkin场景有三部分格式

  1. 鉴于一些初始状态
  2. 当行为发生时
  3. 然后验证结果

behave运行测试时每个步骤由装饰器“粘合”到Python函数。

安装

作为先决条件请确保在你的计算机上安装了Python和pip。 我强烈建议使用Python 3.(我还建议使用pipenv,但以下示例命令使用更基本的pip。)

behave框架只需要一个包:

pip install behave

其他包也可能有用,例如:

pip install requests    # 用于调用REST API
pip install selenium    # 用于web浏览器交互

GitHub上的behavior-driven-Python项目包含本文中使用的示例。

Gherkin特点

behave框架使用的Gherkin语法实际上是符合官方的Cucumber Gherkin标准的。 .feature文件包含功能Feature部分而Feature部分又包含具有Given-When-Then步骤的场景Scenario部分。 以下是一个例子:

Feature: Cucumber Basket
  As a gardener,
  I want to carry many cucumbers in a basket,
  So that I dont drop them all.

  @cucumber-basket
  Scenario: Add and remove cucumbers
    Given the basket is empty
    When "4" cucumbers are added to the basket
    And "6" more cucumbers are added to the basket
    But "3" cucumbers are removed from the basket
    Then the basket contains "7" cucumbers

这里有一些重要的事情需要注意:

  • Feature和Scenario部分都有简短的描述性标题
  • 紧跟在Feature标题后面的行是会被behave框架忽略掉的注释。将功能描述放在那里是一种很好的做法。
  • Scenarios和Features可以有标签注意@cucumber-basket标记)用于钩子和过滤(如下所述)。
  • 步骤都遵循严格的Given-When-Then顺序
  • 使用AndBut可以为任何类型添加附加步骤。
  • 可以使用输入对步骤进行参数化——注意双引号里的值。

通过使用场景大纲,场景也可以写为具有多个输入组合的模板:

Feature: Cucumber Basket

  @cucumber-basket
  Scenario Outline: Add cucumbers
    Given the basket has “<initial>” cucumbers
    When "<more>" cucumbers are added to the basket
    Then the basket contains "<total>" cucumbers

    Examples: Cucumber Counts
      | initial | more | total |
      |    0    |   1  |   1   |
      |    1    |   2  |   3   |
      |    5    |   4  |   9   |

场景大纲总是有一个Examples表其中第一行给出列标题后续每一行给出一个输入组合。 只要列标题出现在由尖括号括起的步骤中,行值就会被替换。 在上面的示例中,场景将运行三次,因为有三行输入组合。 场景大纲是避免重复场景的好方法。

Gherkin语言还有其他元素但这些是主要的机制。 想了解更多信息请阅读Automation Panda这个网站的文章Gherkin by ExampleWriting Good Gherkin

Python机制

每个Gherkin步骤必须“粘合”到步骤定义即提供了实现的Python函数。 每个函数都有一个带有匹配字符串的步骤类型装饰器。 它还接收共享的上下文和任何步骤参数。 功能文件必须放在名为features/的目录中,而步骤定义模块必须放在名为features/steps/的目录中。 任何功能文件都可以使用任何模块中的步骤定义——它们不需要具有相同的名称。 下面是一个示例Python模块其中包含cucumber basket功能的步骤定义。

from behave import *
from cucumbers.basket import CucumberBasket

@given('the basket has "{initial:d}" cucumbers')
def step_impl(context, initial):
    context.basket = CucumberBasket(initial_count=initial)

@when('"{some:d}" cucumbers are added to the basket')
def step_impl(context, some):
    context.basket.add(some)

@then('the basket contains "{total:d}" cucumbers')
def step_impl(context, total):
    assert context.basket.count == total

可以使用三个步骤匹配器parsecfparsere。默认和最简单的匹配器是parse,如上例所示。注意如何解析参数化值并将其作为输入参数传递给函数。一个常见的最佳实践是在步骤中给参数加双引号。

每个步骤定义函数还接收一个上下文变量,该变量保存当前正在运行的场景的数据,例如feature, scenariotags字段。也可以添加自定义字段,用于在步骤之间共享数据。始终使用上下文来共享数据——永远不要使用全局变量!

behave框架还支持钩子来处理Gherkin步骤之外的自动化问题。钩子是一个将在步骤场景功能或整个测试套件之前或之后运行的功能。钩子让人联想到面向方面的编程。它们应放在features/目录下的特殊environment.py文件中。钩子函数也可以检查当前场景的标签,因此可以有选择地应用逻辑。下面的示例显示了如何使用钩子为标记为@web的任何场景生成和销毁一个Selenium WebDriver实例。

from selenium import webdriver

def before_scenario(context, scenario):
    if 'web' in context.tags:
        context.browser = webdriver.Firefox()
        context.browser.implicitly_wait(10)

def after_scenario(context, scenario):
    if 'web' in context.tags:
        context.browser.quit()

注意:也可以使用fixtures进行构建和清理。

要了解一个behave项目应该是什么样子,这里是示例项目的目录结构:

任何Python包和自定义模块都可以与behave框架一起使用。 使用良好的设计模式构建可扩展的测试自动化解决方案。步骤定义代码应简明扼要。

运行测试

要从命令行运行测试,请切换到项目的根目录并运行behave命令。 使用-help选项查看所有可用选项。

以下是一些常见用例:

# run all tests
behave

# run the scenarios in a feature file
behave features/web.feature

# run all tests that have the @duckduckgo tag
behave --tags @duckduckgo

# run all tests that do not have the @unit tag
behave --tags ~@unit

# run all tests that have @basket and either @add or @remove
behave --tags @basket --tags @add,@remove

为方便起见,选项可以保存在config文件中。

其他选择

behave不是Python中唯一的BDD测试框架。其他好的框架包括

  • pytest-bddpytest的插件,和behave一样它使用Gherkin功能文件和步骤定义模块但它也利用了pytest的所有功能和插件。例如,它可以使用pytest-xdist并行运行Gherkin场景。 BDD和非BDD测试也可以与相同的过滤器一起执行。 pytest-bdd还提供更灵活的目录布局。
  • radish是一个“Gherkin增强版”框架——它将Scenario循环和前提条件添加到标准的Gherkin语言中这使得它对程序员更友好。它还提供丰富的命令行选项behave
  • lettuce是一种较旧的BDD框架behave非常相似在框架机制方面存在细微差别。然而GitHub最近显示该项目的活动很少截至2018年5月

任何这些框架都是不错的选择。

另外请记住Python测试框架可用于任何黑盒测试即使对于非Python产品也是如此 BDD框架非常适合Web和服务测试因为它们的测试是声明性的而Python是一种很好的测试自动化语言

本文基于作者的PyCon Cleveland 2018演讲,行为驱动的Python


via: https://opensource.com/article/18/5/behavior-driven-python

作者:Andrew Knight 选题:lujun9972 译者:Flowsnow 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出