Behave 快速指南



Behave - 简介

Behave 是一个用于在Python编程语言中进行行为驱动开发 (BDD) 的工具。在敏捷开发框架中,BDD 创造了一种文化,在这种文化中,测试人员、开发人员、业务分析师以及项目的其他利益相关者都可以为软件开发做出贡献。

简而言之,技术人员和非技术人员都在整个项目中发挥作用。Behave 的测试是用纯文本开发的,实现逻辑是用 Python 编写的。

BDD 格式始于类似故事的软件特性描述。

然后继续开发并执行以下任务:

  • 为特性开发失败的测试用例。

  • 实现通过测试的逻辑。

  • 代码重构以满足项目指南。

有很多 BDD 库,例如支持 JavaScript 的 Mocha,支持 Java/Ruby 的 Cucumber,支持 Python 的 Behave,等等。

在本教程中,我们将详细讨论 Behave。

让我们看看 BDD 的基本结构。它主要包括特性文件、步骤定义文件等。

特性文件

Behave 中的特性文件可以如下所示:

Feature − Verify book name added in Library.
Scenario − Verify Book name.
Given − Book details.
Then − Verify book name.

相应的步骤定义文件

以下是 Behave 工具中相应的定义文件:

from behave import *
@given('Book details')
def impl_bk(context):
   print('Book details entered')
@then('Verify book name')
def impl_bk(context):
   print('Verify book name')

输出

运行特性文件后获得的输出如下:

Behaviour Driven Development

输出显示特性和场景名称,以及测试结果和各个测试执行的持续时间。

Behave - 安装

Behave 的安装可以通过以下几种方式完成:

使用 pip

要安装 Behave,我们应该在系统中安装pip – Python 语言的包安装程序。如果 Python 版本大于 2(直到 2.7.9),则默认安装 pip。

要安装 pip,请运行以下命令:

pip install pip

要使用Behave安装 pip,请运行以下命令:

pip install behave

您的计算机上将出现以下屏幕:

Behave Installation

我们可以使用以下命令更新现有版本的 Behave:

pip install –U behave

我们也可以使用easy_install安装 Behave。

要安装 Setuptools,请运行以下命令:

pip install setuptools

现在,要安装 Behave,请运行以下命令

easy_install behave

我们可以使用以下命令更新现有版本的 behave:

easy_install –U behave

使用源代码分发

解压 Behave 的源代码分发包后,键入新生成的目录'behave-<version>' 并执行以下命令:

python setup.py install

使用 Git 仓库

我们首先应该在系统中安装 pip。

之后,要使用 Git 仓库安装最新版本的 Behave,请运行以下命令:

pip install git+https://github.com/behave/behave

如果我们使用PyCharm 编辑器编写 Behave 代码,则应该安装专业版的 PyCharm 以及与之一起安装的 Gherkin 插件。

Behave - 命令行

Behave 有一组命令行参数,也可以从配置文件中概述。配置文件中设置的值会自动使用,但是可以通过命令行参数覆盖。

命令行参数

让我们讨论一些命令行参数:

  • –c, --no-color

削弱 ANSI 颜色转义符的使用。

  • --color -

使用 ANSI 颜色转义符。这是一个内置特性,可以覆盖配置文件中的设置。

  • –d, --dry-run

调用格式化程序而不运行步骤。

  • -D, --define

声明 config.userdata 字典的自定义信息。

  • –e, --exclude Pattern

从执行中排除与正则表达式模式相同的特性文件。

  • –i, --include Pattern

在执行期间包含与正则表达式模式相同的特性文件。

  • --no-junit

省略 JUnit 报告作为输出。

  • --junit

添加 JUnit 报告作为输出。启用 JUnit 时,每个 stdout 和 stderr 都会成为 junit 报告的一部分。(与 -capture/-no-capture 选项无关)。

  • –f, --format

定义格式化程序。如果省略,则使用内置格式化程序。–format-help 命令将显示所有可用的格式。

  • -steps-catalog

显示所有现有步骤定义的目录。

  • –k, --no-skipped

从控制台打印中排除跳过的步骤。

  • no-snippets

从控制台打印中排除尚未实现的步骤的代码片段。

  • --snippets

在控制台打印中包含尚未实现的步骤的代码片段。这是一个内置特性,可以覆盖配置文件设置。

  • –m, --no-multiline

排除步骤下的多行表和字符串。

  • --multiline

包含步骤下的多行表和字符串。这是一个内置特性,可以覆盖配置文件设置。

  • –n, --name

包含在运行中与指定名称相同的特性元素。如果多次提供此选项,它将与所有名称匹配。

  • --no-capture

排除捕获 stdout。

  • --capture

包含 stdout。这是一个内置特性,可以覆盖配置文件设置。

  • --no-capture-stderr

排除捕获 stderr。

  • --capture-stderr

包含 stderr。这是一个内置特性,可以覆盖配置文件设置。

  • --no-logcapture

排除捕获日志。

  • --logcapture

包含日志捕获。步骤的每个日志都将在失败时出现并可用。这是一个内置特性,可以覆盖配置文件设置。

  • --logging-level

提及要捕获的日志记录级别。默认值为 INFO。

  • --logging-format

提及用于打印语句的用户定义格式。默认值为 %(levelname)s:%(name)s:%(message)s。

  • --logging-datefmt

提及用于打印语句的用户定义日期和时间格式。

  • --logging-filter

提及是否要过滤语句。默认情况下捕获所有语句。如果输出太长,我们可以使用此选项过滤掉不必要的输出。

  • --logging-clear-handlers

删除所有用于日志记录的处理程序。

  • --no-summary

排除执行后的摘要。

  • -summary

包含执行后的摘要。

  • –o, --outfile

写入给定文件而不是使用 stdout。

  • –q, --quiet

是 –no-snippets –no-source 的别名。

  • –s, --no-source

排除打印步骤定义的文件和行以及步骤。

  • --show-source

包含打印步骤定义的文件和行以及步骤。这是一个内置特性,可以覆盖配置文件设置。

  • --stage

描述测试的当前阶段。阶段名称用作环境文件的名称后缀,以及步骤的目录。
  • --stop

遇到第一个失败后终止执行测试。

  • –t, --tags

包含在执行中具有与 TAG_EXPRESSION 相同的标签的特性/场景。

  • –T, --no-timings

排除打印每个步骤的执行持续时间。

  • --show-timings

捕获每个步骤在控制台中完成所需的时间(以秒为单位)。这是一个内置特性,可以覆盖配置文件设置。

  • –v, --verbose

显示加载的特性和文件。

  • –w, --wip

执行具有 wip 标签的场景。此外,我们必须使用纯格式化程序,并且不记录 stdout 或日志输出,并在第一次失败后终止。

  • –x, --expand

在输出中展平场景大纲的表。

  • --lang

使用除英语以外的语言的关键字。

  • --lang-list

显示 –lang 中的所有语言。

  • --lang-help

显示为单一语言获取的所有翻译。

  • --tags-help

显示标签语句的帮助。

  • --version

显示版本。

  • junit –directory

这是存储 Junit 报告的目录位置。

  • --show-skipped

在控制台打印中包含跳过的步骤。这是一个内置特性,可以覆盖配置文件设置。

Behave - 配置文件

Behave 配置文件被称为.behaverc/behave.ini/setup.cfg/tox.ini(任选其一,由用户选择)。

这些文件可以位于以下位置:

  • 当前工作目录。

  • 用户主目录。

  • 对于 Windows 用户,位于 %APPDATA% 目录下。

命令behave –v将显示所有配置详细信息。配置文件应以关键字[behave]开头,并遵循Windows INI样式格式。

例如:

[behave]
format = plain
dry_run = false

参数类型

Behave中的配置参数类型包括以下几种:

  • 文本 (Text) - 为配置设置赋值文本。

  • 布尔值 (Bool) - 为配置设置赋布尔值。文本定义行为(真值包括1、true、yes和on)。假值包括0、false、no和off)。

  • 序列<文本> (Sequence<text>) - 在换行符上接受多个值。

例如,标签表达式可以如下所示:

tags=@a, ~@b
         @c

这等效于以下标签表达式:

--tags @a, ~@b --tags @c

配置参数

下面解释Behave中的一些配置参数:

  • color - bool

使用ANSI颜色转义符。这是一个内置特性,可以覆盖配置文件中的设置。

  • dry_run - bool

调用格式化程序但不运行步骤。

  • userdata_defines - sequence<text>

声明config.userdata字典的自定义数据。

  • exclude_re - text

从执行中排除与正则表达式模式相同的特征文件。

  • include_re - text

在执行期间包含与正则表达式模式相同的特征文件。

  • junit - bool

添加 JUnit 报告作为输出。启用 JUnit 时,每个 stdout 和 stderr 都会成为 junit 报告的一部分。(与 -capture/-no-capture 选项无关)。

  • junit_directory - text

这是存储JUnit报告的目录位置。

  • default_format - text

声明默认格式化程序。默认值为pretty。

  • format: sequence<text>

定义格式化程序。如果省略,则使用内置格式化程序。–format-help 命令将显示所有可用的格式。

  • steps_catalog - bool

显示所有现有步骤定义的目录。

  • scenario_outline_annotation_schema: text

指定场景轮廓的注释模式。

  • show_skipped - bool

在控制台中打印时包含跳过的步骤。这是一个内置特性,可以覆盖配置文件设置。

  • show_snippets - bool

在控制台中打印尚未实现的步骤的代码片段。这是一个内置特性,可以覆盖配置文件设置。

  • show_multiline - bool

包含步骤下的多行表和字符串。这是一个内置特性,可以覆盖配置文件设置。

  • name - sequence<text>

包含在运行中与指定名称相同的特征元素。如果多次提供此选项,它将匹配所有指定的名称。

  • stdout_capture - bool

包含 stdout。这是一个内置特性,可以覆盖配置文件设置。

  • stderr_capture - bool

包含 stderr。这是一个内置特性,可以覆盖配置文件设置。

  • log_capture - bool

包含日志捕获。步骤的每个日志都将在失败时出现并可用。这是一个内置特性,可以覆盖配置文件设置。

  • logging_level - text

指定要捕获的日志级别。默认值为INFO。

  • logging_format - text

指定打印语句的用户自定义格式。默认值为%(levelname)s:%(name)s:%(message)s。

  • logging_datefmt - text

指定打印语句的用户自定义日期和时间格式。

  • logging_filter - text

指定要过滤的语句。默认情况下捕获所有语句。如果输出过长,我们可以使用此选项过滤掉不必要的输出。

  • logging_clear_handlers : bool

删除所有用于日志记录的处理程序。

  • summary - bool

执行后包含摘要。

  • outfiles - sequence<text>

写入给定文件而不是使用 stdout。

  • paths - sequence<text>

指定特征文件的默认路径。

  • quiet - bool

别名为 –no-snippets –no-source。

  • show-source - bool

包含打印步骤的步骤定义文件和行号。这是一个内置特性,可以覆盖配置文件设置。

  • stage - text

描述测试的当前阶段。阶段名称用作环境文件和步骤目录的名称后缀。

  • stop - bool

遇到第一个失败后终止执行测试。

  • tags - sequence<text>

包含在执行中具有与TAG_EXPRESSION相同的标签的特性/场景。

  • default_tags - text

如果没有给出,则声明默认标签。

  • show_timings - bool

捕获每个步骤在控制台中完成所需的时间(以秒为单位)。这是一个内置特性,可以覆盖配置文件设置。

  • verbose - bool

显示加载的特性和文件。

  • wip - bool

执行具有 wip 标签的场景。此外,我们必须使用纯格式化程序,并且不记录 stdout 或日志输出,并在第一次失败后终止。

  • expand - bool

在输出中展平场景大纲的表。

  • lang - text

使用除英语以外的语言的关键字。

Behave - 特性测试设置

Behave 使用三种不同的文件类型,如下所示:

  • 特征文件 (Feature files) 由业务分析师或任何项目干系人创建,包含与行为相关的用例。

  • 步骤实现文件 (Step Implementation file) 用于特征文件中定义的场景。

  • 环境设置文件 (Environment Setup files) 在这里,在步骤、特性、场景等之前和之后执行前后条件。

特性文件

特征文件应该在一个名为features的文件夹中。此外,features目录中应该有一个名为steps的子目录。

Feature File

启动特征文件

我们可以使用各种命令行参数启动特征文件。这些将在下面解释:

  • 如果没有可用信息,则将加载features目录中的所有特征文件以在Behave中执行。

  • 如果提供了features目录的路径,则必须至少有一个特征文件(扩展名为.feature)和一个名为steps的子目录。

  • 此外,如果存在environment.py,它应该位于包含steps目录的目录中,而不是steps目录内。

  • 如果提供了特征文件的路径,则它指示Behave搜索该文件。为了获得该特征文件的相应步骤目录,将搜索父目录。

  • 如果在当前父目录中找不到,则搜索其父目录。这将持续进行,直到到达文件系统根目录。此外,如果存在environment.py,它应该位于包含steps目录的目录中,而不是steps目录内。

Behave - Gherkin 关键字

Behave中的Gherkin关键字列在下面:

  • 特性 (Features)

  • 场景 (Scenario)

  • 步骤 (Steps)

  • 背景 (Background)

  • 场景轮廓 (Scenario Outline)

  • 文本 (Text)

  • 表格 (Table)

  • 标签 (Tags)

  • 给定 (Given)

  • 当 (When)

  • 然后 (Then)

  • 但是 (But)

  • 并且 (And)

特征文件是用Gherkin语言编写的。它是纯文本,由团队的非技术成员(业务分析师)创建。特征文件可用于自动化测试和文档。

换行符结束语句包含在Behave中。我们可以使用制表符/空格进行缩进。大多数行以关键字开头,例如Scenario、Given、Then等。可以在文件的任何位置添加注释。它们以/不以空格开头,后跟#符号和文本。

让我们讨论一些关键的Gherkin关键字。

特性 (Feature)

一个特性包含场景。它们可以包含/不包含描述、背景和一组标签。

特征文件的结构如下:

Feature − Verify book name added in Library
Scenario − Verify Book name
Given Book details
Then Verify book name

特性的名称应该对正在测试的特性进行描述。但是,冗长的描述不是强制性的,只添加描述是为了消除特性名称中的歧义。

背景 (Background)

添加背景是为了有一组步骤。它类似于一个场景。我们可以使用背景为多个场景添加上下文。它在每个场景之前运行,但在before hooks执行之后运行。

背景通常用于执行前提条件,例如登录场景或数据库连接等。

可以添加背景描述以提高人类的可读性。背景只能在一个特征文件中出现一次,并且必须在场景或场景轮廓之前声明。

不应使用背景来创建复杂的状态(只有在无法避免的情况下)。此部分应简短且真实。此外,我们应该避免在一个特征文件中包含大量场景。

包含背景的特征文件

包含Background关键字的特征文件如下:

Feature: Payment Process
   Background:
      Given launch application
      Then Input credentials
   Scenario: Credit card transaction
      Given user is on credit card payment screen
      Then user should be able to complete credit card payment
   Scenario: Debit card transaction
      Given user is on debit card payment screen
      Then user should be able to complete debit card payment

场景 (Scenario)

场景定义了正在测试的应用程序的行为。它有一个标题来描述其目标。可以添加其描述以提高人类的可读性。

场景可以有多个步骤,这些步骤以关键字Given、Then、When等开头。建议使用场景来检查单个特性或预期结果。

包含场景的特征文件

包含Scenario关键字的特征文件如下:

Feature − Payment Process
      Scenario − Credit card transaction
   Given user is on credit card payment screen
   Then user should be able to complete credit card payment

场景轮廓 (Scenario Outline)

如果我们有一组类似的条件和要在场景中传递的结果,则使用场景轮廓。场景轮廓附带一个示例表,并且可以有多个示例表。

对于示例表标题行后的每一行,测试都会执行一次。要测试的值由括号<>中包含的名称表示。这些名称应与示例表标题匹配。

它有助于减少代码行数,因为它消除了重复的步骤并对我们的测试进行排序。

包含场景轮廓的特征文件

包含Scenario Outline关键字的特征文件如下:

Feature − User information
Scenario Outline: Check login functionality
   Given user enters <email> and <password>
   Then user should be logged in

示例

以下是包含Scenario Outline的特征文件的示例:

Examples: Credentials
   | email        | password  |
   | qa@gmail.com | pwd1      |
   | qe@gmail.com | pwd2      |

使用不同的参数集执行相同的测试。

给定 (Given)

以关键字Given开头的步骤用于在用户与系统交互之前将系统置于熟悉的环境中(类似于前提条件)。建议不要在Given步骤中描述用户操作。

可以添加Given步骤来设置数据库中的配置、登录应用程序等。

包含Given的特征文件

包含Given关键字的特征文件如下:

Feature − Payment Process
            Scenario − Credit card transaction
   Given user is on credit card payment screen
   Then user should be able to complete credit card payment

当 (When)

以关键字When开头的步骤用于添加用户需要执行的基本任务。这样,用户与系统进行通信,从而导致系统状态发生变化或对其他地方产生影响。

包含When的特征文件

包含When关键字的特征文件如下:

Feature − Payment Process
            Scenario − Credit card transaction
   Given user is on credit card payment screen
      When user clicks on the Payment with Credit Card button
   Then user should be able to complete credit card payment

然后 (Then)

以关键字Then开头的步骤用于获得预期结果。在此步骤中观察到的结果(理想情况下为输出形式 - 消息、报告等)应与业务场景和包含它的特征文件相关联。

建议不要将Then步骤用于数据库场景,因为它基本上用于描述最终用户可见的后果。

包含Then的特征文件

包含When关键字的特征文件如下:

Feature − Payment Process
            Scenario − Credit card transaction
   Given user is on credit card payment screen
   When user clicks on the Payment with Credit Card button
   Then user should be able to complete credit card payment

And, But

如果我们有多个连续的Given、When、Then步骤,我们可以使用And和But步骤。它为用户带来了更好的可读性。

包含多个连续Then/Given步骤的特征文件

Behave中包含多个连续Then/Given步骤的特征文件如下:

Feature − Verify book names added in Library
   Scenario − Verify Book name
      Given Book1 details
      Given Book2 details
      Then Verify book names
      Then Verify newly added book names should not be in Delete History

不包含多个Then/Given步骤的特征文件

不包含多个Then/Given步骤的特征文件如下:

Feature − Verify book names added in Library
   Scenario − Verify Book name
      Given Book1 details
      And Book2 details
      Then Verify book names
         But Verify newly added book names should not be in Delete History

步骤数据 - 表格 (Step Data – Table)

步骤可以包含与其关联的文本和数据表。我们可以使用步骤添加数据表。建议将表格数据缩进,并且必须为每一行具有相等的列数。

列数据应由|符号分隔。

包含表格的特征文件

包含table关键字的特征文件如下:

Feature − User Registration
Scenario − User enters registration details
   When User enters name and password
      | name |password |
      | t1   | pwd     |
      | t2   | pwd1    |
Then user should be able to complete registration

表格可通过上下文变量中的.table属性(传递到步骤函数中)访问Python代码。表格是Table的一个实例。

表格的实现逻辑

以下是表格中.table属性的实现逻辑:

@when('User enters name and password')
def step_impl(context):
   for r in context.table:
      model.delete_usr(name=r['name'], password=r['password'])

步骤数据 - 文本 (Step Data – Text)

步骤后用"""括起来的文本块将与该步骤关联。此处将解析缩进。文本开头的所有空格都将被移除。此外,后续所有行的开头都必须至少有一个空格。

文本可以通过上下文变量(在步骤函数中传递)中的.text属性访问实现Python代码。

包含文本的特性文件

包含文本关键字的特性文件如下:

Feature − Verify book name added in Library
   
   Scenario − Verify Book name
      Given Book details
         """
          Text added for a step
         """
      Then Verify book name

标签 (Tags)

可以标记特性文件的一部分,以便Behave能够仅验证特性文件中的特定部分。仅可以标记场景、特性和场景大纲。

此外,用于特性的标签将被其所有场景和场景大纲继承。标签放置在我们要标记的场景或特性之前。我们也可以在一行中用空格分隔多个标签。标签以@开头,后跟标签名称。

包含标签的特性文件

包含标签关键字的特性文件如下:

@payment
@high
Feature − Payment Process
      Scenario − Credit card transaction
   Given user is on credit card payment screen
   Then user should be able to complete credit card payment

标签通过根据标签排除/包含特定场景或特性来帮助管理测试执行。

Behave - 特性文件

如前所述,Behave 使用三种不同的文件类型。这些文件如下:

  • 特性文件由业务分析师或任何项目干系人创建,包含与行为相关的用例。

  • 步骤实现文件 (Step Implementation file) 用于特征文件中定义的场景。

  • 环境设置文件在其中执行步骤、特性、场景等的预/后置条件。

特性文件应位于名为features的文件夹中。此外,features目录中还应该有一个名为steps的子目录。

您的计算机上将出现以下屏幕:

Features Directory

启动特征文件

我们可以使用各种命令行参数启动特性文件,如下所述:

  • 如果没有任何可用信息,则将加载features目录中的所有特性文件以供Behave执行。

  • 如果提供了features目录的路径,则必须至少有一个特征文件(扩展名为.feature)和一个名为steps的子目录。

  • 此外,如果存在environment.py,它应该位于包含steps目录的目录中,而不是steps目录内。

  • 如果提供了特征文件的路径,则它指示Behave搜索该文件。为了获得该特征文件的相应步骤目录,将搜索父目录。

  • 如果在当前父目录中找不到,则搜索其父目录。这将持续进行,直到到达文件系统根目录。此外,如果存在environment.py,它应该位于包含steps目录的目录中,而不是steps目录内。

特性文件的结构

一个特性包含场景。它们可以包含/不包含描述、背景和一组标签。

特性文件的结构如下:

特性文件

特性文件的格式如下:

Feature − Verify book name added in Library
   Scenario − Verify Book name
      Given Book details
      Then Verify book name

对应的步骤实现文件。

对应的步骤实现文件如下所示:

from behave import *
@given('Book details')
def impl_bk(context):
      print('Book details entered')
@then('Verify book name')
def impl_bk(context):
      print('Verify book name')

输出

运行特性文件后获得的输出如下:

Feature and Scenario Names

输出显示特性和场景名称,以及测试结果和测试执行持续时间。

Behave - 步骤实现

Behave中特性文件中场景的步骤应具有用Python编写的实现逻辑。这被称为实现/步骤定义文件(.py扩展名),应位于steps目录中。

此文件中包含所有必要的导入。steps目录应是features目录的一部分。

您的计算机上将出现以下屏幕:

Step Implementations

步骤定义文件包含定义特性文件中步骤的Python函数。在Python函数的开头,必须使用以@given、@when等开头的装饰器。这些装饰器将与特性文件中的Given、Then、When和其他步骤进行比较和匹配。

特性文件

特性文件如下:

Feature − Verify book name added in Library
   Scenario − Verify Book name
      Given Book details
      Then Verify book name

对应的步骤实现文件

对应的步骤实现文件如下所示:

from behave import *
@given('Book details')
def impl_bk(context):
      print('Book details entered')
@then('Verify book name')
def impl_bk(context):
      print('Verify book name')

输出

运行特性文件后获得的输出如下:

Corresponding Step Implementation File

输出显示特性和场景名称,以及测试结果和测试执行持续时间。

Behave - 初级步骤

让我们创建一个基本的Behave测试。

特性文件

标题为“支付类型”的特性的特性文件如下:

Feature − Payment Types
   
   Scenario − Verify user has two payment options
      Given User is on Payment screen
      When User clicks on Payment types
      Then User should get Types Cheque and Cash

对应的步骤实现文件

上述特性的对应步骤实现文件如下:

from behave import *
@given('User is on Payment screen')
def impl_bkpy(context):
      print('User is on Payment screen')
@when('User clicks on Payment types')
def impl_bkpy(context):
      print('User clicks on Payment types')
@then('User should get Types Cheque and Cash')
def impl_bkpy(context):
      print('User should get Types Cheque and Cash')

项目结构

特性“支付类型”的项目结构如下:

Payment Types

输出

运行特性文件后获得的输出如下所示,此处使用的命令为behave

Running the Feature File

输出显示特性和场景名称,以及测试结果和测试执行持续时间。

Python控制台输出如下:

Python Console

Behave - 支持的语言

我们可以选择在特性文件中使用英语以外的其他语言。这是因为大多数BDD工具都支持国际化。重要的是,关键字Then、When、Given可以用其他本地语言(如西班牙语、法语等)来描述。

在这种情况下,开发人员也可以使用其他语言实现步骤定义。可以使用以下命令获取所有语言的列表:behave --lang-list。

使用命令behave --lang-list后,您的计算机上将显示以下屏幕:

Supported Languages

Behave中包含的其他一些语言如下:

Particular Language

特性文件可以与特定语言关联。此时,BDD框架将为该特定语言选择关键字。可以在配置文件中将语言设置为默认语言。

Behave配置文件可以是.behaverc或behave.ini文件。如果我们希望语言为丹麦语,则应在配置文件中将参数lang的值设置为da。

配置文件设置

选择特定语言的特性文件设置如下所示,示例中使用的语言为丹麦语 (da)。

[behave]
lang = da

Behave - 步骤参数

我们可以将参数传递给Behave中的步骤。让我们来看一个包含具有多个参数的步骤的特性文件,其中设置了不同的值。这有助于简化自动化实现,因为减少了步骤定义的总数。

特性文件

请考虑以下特性文件示例:

Feature − Schedule
   Scenario − Verify Day and Night Schedule
   Given I reach office at "day" shift
   And I reach office at "night" shift

特性文件包含与Given和And步骤中几乎相同的步骤。唯一的区别在于昼夜班的时间。无需为几乎相同的步骤重复实现,我们可以将参数传递给步骤定义文件中的步骤。

请注意:我们在特性文件中将昼夜参数放在双引号文本中(也可以使用单引号文本)。在步骤实现中,我们将传递用{}括起来的参数。

此外,参数作为参数之一传递给实现方法。

对应的步骤实现文件

对应的步骤实现文件如下:

from behave import *
@given('I reach office at "{time}" shift')
def step_implpy(context, time):
      print("Shift is: {}".format(time))

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

Step Parameters

输出显示打印了Shift is: dayShift is: night。此处,参数day和night是从步骤中传递的。

Behave - 场景轮廓

如果我们有一组类似的标准并且结果要传递到场景中,则使用场景大纲。场景大纲附带一个示例表。场景大纲可以有多个示例表。

对于示例表中(标题行之后)找到的每一行,测试都会执行一次。要测试的值由括号<>中包含的名称表示。这些名称应与示例表标题匹配。

它有助于减少代码行数(消除重复步骤)并组织我们的测试。

特性文件

场景大纲的特性文件如下:

Feature − User information
Scenario Outline: Check login functionality
   Given user enters "<name>" and "<password>"
   Then user should be logged in
   Examples: Credentials
      | name   | password |
      | user1  | pwd1     |
      | user2  | pwd2     |

请注意:我们将名称和密码参数括在“<>”中。这些参数是示例部分下方提供的列标题。在步骤实现中,我们将传递用“{}”括起来的参数。

此外,这些参数需要作为参数传递给实现方法。

对应的步骤实现文件

对应的步骤实现文件如下:

from behave import *
@given('user enters "{name}" and "{password}"')
def step_implpy(context, name, password):
      print("Username for login: {}".format(name))
         print("Password for login: {}".format(password))
@then('user should be logged in')
def step_implpy(context):
      pass

输出

运行特性文件后获得的输出,使用的命令为behave --no-capture -f plain

Scenario Outlines

输出显示打印了Username for login: user1, Password for login: pwd1Username for login: user2, Password for login: pwd2。此处,从示例中传递了两个数据集。

Behave - 多行文本

步骤后用"""括起来的文本块将与该步骤关联。此处将解析缩进。文本开头的所有空格都将被移除,后续所有行的开头都必须至少有一个空格。

文本可以通过上下文变量(在步骤函数中传递)中的.text属性访问实现Python代码。

特性文件

标题为用户信息的特性的特性文件如下:

Feature − User information
Scenario − Check login functionality
   Given user enters name and password
         """
         Tutorialspoint Behave
          Topic – Multiline Text
         """
   Then user should be logged in

对应的步骤实现文件

特性的对应步骤实现文件如下:

from behave import *
@given('user enters name and password')
def step_impl(context):
#access multiline text with .text attribute
      print("Multiline Text: " + context.text)
@then('user should be logged in')
def step_impl(context):
      pass

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

Multiline Text

输出显示打印了多行文本。

Behave - 设置表

步骤可以包含与其关联的文本和数据表。我们可以使用步骤添加数据表。建议将表格数据缩进,并且必须为每一行具有相等的列数。

列数据应由|符号分隔。

包含表格的特性文件 (Login.feature)

特性文件如下所示:

Feature − User Information
Scenario − Check login functionality
   Given Collection of credentials
      | username |password |
      | user1    | pwd1    |
      | user2    | pwd2    |
   Then user should be logged in

表可以通过上下文变量(在步骤函数中传递)中的.table属性访问实现Python代码。表是Table的实例。我们可以使用设置表来促进测试设置。

Python 代码

访问表 (login_module.py) 的Python代码如下:

class Deprt(object):
   def __init__(self, username, ms=None):
      if not ms:
         ms = []
      self.username = username
      self.ms = ms
   def m_addition(self, usernane):
      assert usernane not in self.ms
      self.ms.append(usernane)
class LModel(object):
   def __init__(self):
      self.loginusrs = []f
      self.passwords = {}
   def usr_addition(self, username, password):
      assert username not in self.loginusrs
      if password not in self.passwords:
         self.passwords[password] = Deprt(password)
      self.passwords[password].m_addition(username)

对应的步骤实现文件 (step_implg.py)

文件如下:

from behave import *
from features.steps.login_module import LModel
@given('Collection of credentials')
def step_impl(context):
   model = getattr(context, "model", None)
   if not model:
      context.model = LModel()
   #iterate rows of table
    for r in context.table:
      context.model.usr_addition(r["username"], password=r["password"])
@then('user should be logged in')
def step_impl(context):
   pass

项目设置

Python项目中文件的项目设置如下:

Project Setup

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

Setup Table

输出显示打印了设置表。

Behave - 步骤中的步骤

我们可以用一个宏步骤替换场景中的多个步骤。这有助于我们不必在步骤定义文件中重复相同的代码。BDD框架能够从步骤定义中调用多个步骤。

包含相似步骤的特性文件

包含相似步骤的特性文件如下:

Feature − Payment Module
   Scenario − Verify message after payment
      Given User is on payment screen
      When User enters payment details
      And User completes payment
      Then User should get success message
   Scenario − Verify new users can process payment
      Given User keys in payment info and submits
      Then success message should get displayed

在特性文件中,我们有两个具有相似步骤的场景。在Behave中,我们可以在单个步骤中执行多个步骤。这可以通过步骤实现文件中的context.execute_steps方法来实现。

对应的步骤实现文件

上述特性文件的对应步骤实现文件如下:

from behave import *
@given('User is on payment screen')
def is_on_payment_screen(context):
   print('User is on payment screen')
@when('User enters payment details')
def enters_payment_details(context):
   print('When User enters payment details')
@when('User completes payment')
def completes_payment(context):
   print('When User completes payment')
@then('User should get success message')
def get_success_message(context):
   print('Then User should get success message')
   @given('User keys in payment info and submits')
def payment_info_and_submits(context):
#passing steps within steps with context.execute_steps
   context.execute_steps(u"""
      Given User is on payment screen
      When User enters payment details
      And User completes payment
      """)
@then('success message should get displayed')
def success_message(context):
   print('Then success message should get displayed')

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

No Capture

后续输出如下:

Scenario Verify

输出显示,场景“验证”的新用户可以通过执行场景“验证新用户可以处理支付”中的步骤来处理支付。

Behave - 背景

添加背景是为了拥有步骤组。它接近于场景。我们可以使用背景向多个场景添加上下文。它在每个特性的每个场景之前运行,但在before钩子执行之后。

背景通常用于执行前提条件,例如登录场景或数据库连接等。

可以添加背景描述以提高人类可读性。它在一个特性文件中只能出现一次,并且必须在场景或场景大纲之前声明。

背景不应该用于创建复杂的状态(只有在无法避免的情况下才可以使用)。此部分应简洁且真实。此外,我们应该避免在一个特性文件中包含大量的场景。

包含背景的特征文件

名为“支付流程”的特性文件的背景如下:

Feature − Payment Process
   Background:
      Given launch application
      Then Input credentials
   Scenario − Credit card transaction
      Given user is on credit card payment screen
      Then user should be able to complete credit card payment
   Scenario − Debit card transaction
      Given user is on debit card payment screen
      Then user should be able to complete debit card payment

对应的步骤实现文件

文件如下所示:

from behave import *
@given('launch application')
def launch_application(context):
   print('launch application')
@then('Input credentials')
def input_credentials(context):
   print('Input credentials')
@given('user is on credit card payment screen')
def credit_card_pay(context):
   print('User is on credit card payment screen')
@then('user should be able to complete credit card payment')
def credit_card_pay_comp(context):
   print('user should be able to complete credit card pay')
@given('user is on debit card payment screen')
def debit_card_pay(context):
   print('User is on debit card payment screen')
@then('user should be able to complete debit card payment')
def debit_card_pay_comp(context):
   print('user should be able to complete debit card payment')

输出

运行特性文件后获得的输出如下所示,此处使用的命令为behave --no-capture -f plain

Feature File with Background

后续输出如下:

Background

输出显示背景步骤(Given Launch applications & Then Input Credentials)在每个场景之前都运行了两次。

Behave - 数据类型

Behave 中有两种数据类型,分别是预定义类型和用户自定义类型。让我们首先了解预定义数据类型。

预定义数据类型

Behave 利用 parse 模块来解析步骤定义中的参数。让我们探索一些受步骤定义支持并且不需要像用户自定义数据类型那样注册的解析类型。

  • w(字符串类型) - 下划线 & 字母。

  • W(字符串类型) - 下划线 & 非字母。

  • s(字符串类型) - 空格。

  • S(字符串类型) - 非空格。

  • d(整数类型) - 数字。

  • D(字符串类型) - 非数字。

  • n(整数类型) - 带有千位分隔符的数字。

  • %(浮点类型) - 百分比。(转换为 value/100.0)

  • f(浮点类型) - 定点数字。

  • e(浮点类型) - 带指数的浮点数字。

  • g(浮点类型) - 数字格式。

  • b(整数类型) - 二进制数。

  • o(整数类型) - 八进制数。

  • x(整数类型) - 十六进制数。

  • ti(日期时间类型) - ISO 8601 日期/时间格式的时间。

  • te(日期时间类型) - RFC 2822 电子邮件日期/时间格式的时间。

  • tg(日期时间类型) - 全局日期/时间格式的时间。

  • ta(日期时间类型) - 美国日期/时间格式的时间。

  • tc(日期时间类型) - ctime() 日期/时间格式。

  • th(日期时间类型) - HTTP 日志日期/时间格式的时间。

  • tt(时间类型)

在步骤实现中,我们将传递参数:用“{}”括起来的数据类型。

包含 % 数据类型的特性文件

包含 % 数据类型的特性文件如下:

Feature − Payment Process
   Scenario Outline: Credit card transaction
   Given user is on credit card payment screen
   When user makes a payment of "<p>" percent of total
   Examples: Amounts
      | p      |
      |80%     |
      |90%     |

对应的步骤实现文件

文件如下:

from behave import *
@given('user is on credit card payment screen')
def credit_card_pay(context):
   print('User is on credit card payment screen')
#passing parameter in % datatype enclosed in {}
@when('user makes a payment of "{p:%}" percent of total')
def step_impl(context, p):
   print('Number is: ')
   print(p)

输出

运行特性文件后获得的输出,使用的命令为behave --no-capture -f plain

Pre-defined Data types

后续输出如下:

Data Types

输出显示 0.8 和 0.9,这是从 % 数据类型获得的,用于表示从特性文件中传递的 80% 和 90% 值。

用户自定义数据类型

Behave 也具有用户自定义数据类型。register_type 方法用于注册用户自定义类型,该类型可在匹配步骤时用于任何类型转换。

特性文件

名为“支付流程”的特性文件如下:

Feature − Payment Process
   Scenario Outline: Credit card transaction
      Given user is on credit card payment screen
      When user makes a payment of "<amount>" of total
      Examples: Amounts
         |amount  |
         |75      |
         |85      |

在步骤实现中,我们将传递参数:用“{}”括起来的用户自定义数据类型。register_type 方法用于注册用户自定义类型,该类型可在匹配步骤时用于任何类型转换。

对应的步骤实现文件

文件如下:

from behave import *
from behave import register_type
#convert parsed text to float
def parse_percent(t):
   return float(t)
#register user-defined type
register_type(Float=parse_percent)
@given('user is on credit card payment screen')
def credit_card_pay(context):
   print('User is on credit card payment screen')
@when('user makes a payment of "{amount:Float}" of total')
def step_impl(context, amount):
   print('Number is: ')
   print(amount)

输出

运行特性文件后获得的输出,使用的命令为behave --no-capture -f plain

User-defined Data types

后续输出如下:

Float   0
 Values

输出显示75.085.0,它们已转换为浮点值(借助用户自定义转换)。这些参数作为整数类型从特性文件中传递。

Behave - 标签

可以标记特性文件的一部分,以便Behave能够仅验证特性文件中的特定部分。仅可以标记场景、特性和场景大纲。

此外,用于特性的标签将被其所有场景和场景大纲继承。标签放置在我们想要标记的场景或特性之前。我们也可以有多个标签,这些标签在同一行中用空格隔开。

标签以 @ 开头,后跟标签名称。

包含标签的特性文件 (Payment.feature)

包含标签的特性文件如下:

@high
Feature − Payment Process
@creditpayment
            Scenario − Credit card transaction
   Given user is on credit card payment screen
   Then user should be able to complete credit card payment
@debitpayment
            Scenario − Debit card transaction
   Given user is on debit card payment screen
   Then user should be able to complete debit card payment

标签通过根据标签排除/包含特定场景或特性来帮助管理测试执行。

在上面的示例中,要运行带有 creditpayment 标签的特定场景,我们必须运行以下命令:

behave payment.feature --tags=creditpayment

要运行带有 high 标签的特性并执行所有场景,我们必须运行以下命令:

behave payment.feature --tags=high

如果运行以下命令,则表示该命令将执行带有 creditpayment 或 debitpayment 标签的场景。

behave payment.feature --tags= creditpayment, debitpayment

如果运行以下命令,则表示该命令将执行带有 creditpayment 和 debitpayment 标签的两个场景。

behave payment.feature --tags= creditpayment --tags=debitpayment

如果运行以下命令,则表示该命令将不执行带有 creditpayment 标签的场景。

behave payment.feature --tags= ~ creditpayment

因此,包含标签的特性文件 (Payment.feature) 将如下所示:

@high
Feature − Payment Process
@creditpayment @payment
   Scenario − Credit card transaction
      Given user is on credit card payment screen
@debitpayment @payment
      Scenario − Debit card transaction
      Given user is on debit card payment screen
   Scenario − Cheque transaction
      Given user is on cheque payment screen

对应的步骤实现文件

文件如下:

from behave import *
@given('user is on credit card payment screen')
def credit_card_pay(context):
   print('User is on credit card payment screen')
@given('user is on debit card payment screen')
def debit_card_pay(context):
   print('user is on debit card payment screen')
@given('user is on cheque payment screen')
def cheque_pay(context):
   print('user is on cheque payment screen')

输出

运行特性文件后获得的输出如下所示。在这里,我们使用了命令behave --no-capture Payment.feature --tags=payment

No Capture Payment Feature

输出显示两个场景通过,因为特性文件中具有 payment 场景标签的场景有两个。

当我们使用命令behave --no-capture Payment.feature --tags=~creditpayment时,输出如下所示:

Creditpayment

输出显示两个场景通过,因为特性文件中没有 creditpayment 场景标签的场景有两个。

当我们使用命令behave --no-capture Payment.feature --tags=high时,输出如下所示:

Scenario Tag

输出显示三个场景通过,因为特性文件中没有带有 high 标签的特性的场景有三个。

使用命令behave --no-capture Payment.feature --tags=payment,creditpayment可获得以下输出:

Scenario tagged with payment

输出显示两个场景通过,因为特性文件中没有带有 payment 或 creditpayment 标签的场景有两个。

Behave - 枚举

枚举用于将多个不同的基于字符串的单词映射到值。

我们可能需要一个用户自定义数据类型,其具有以下特性:

  • 必须匹配少量单词。

  • 在测试执行之前预定义值。

对于上述场景,可以使用基于字符串的枚举。

特性文件

考虑一下名为“支付流程”的特性的特性文件,如下所示:

Feature − Payment Process
Scenario − Response
      When User asks "Is payment done?"
      Then response is "No"

在步骤实现文件中,TypeBuilder.make_enum 函数评估为提供的单词或字符串枚举的正则表达式模式。register_type 方法用于注册用户自定义类型,该类型可在匹配步骤时用于任何类型转换。

此外,我们将传递参数:用“{}”括起来的用户自定义枚举数据类型。

对应的步骤实现文件

上述特性的步骤实现文件如下所示:

from behave import *
from behave import register_type
from parse_type import TypeBuilder
# -- ENUM: Yields True (for "yes"), False (for "no")
parse_response = TypeBuilder.make_enum({"yes": True, "no": False})
register_type(Response=parse_response)
@when('User asks "{q}"')
def step_question(context, q):
   print("Question is: ")
   print(q)
@then('response is "{a:Response}"')
def step_answer(context, a):
   print("Answer is: ")
   print(a)

输出

运行特性文件后获得的输出如下所示。在这里,我们使用了命令behave --no-capture -f plain

Enumeration Data Type

输出显示Is payment done?False。False 输出来自枚举数据类型。

Behave - 步骤匹配器

Behave 中有三种步骤匹配器。它们解释如下:

  • ParseMatcher (parse) - 基于 parse 模块。

  • 扩展的 ParseMatcher (cfparse) - 允许基数语法。

  • RegexMatcher (re) - 基于正则表达式来匹配模式。

Parse 匹配器

这是内置的步骤匹配器,具有以下特性:

  • 易于使用和理解。

  • 预定义和用户自定义数据类型支持此匹配器。

  • 借助数据类型重新利用正则表达式。

  • 隐藏正则表达式的复杂性。

扩展的 Parse 匹配器

它扩展了 Parse 匹配器。除了 Parse 匹配器的特性外,它还具有其他特性。

附加特性包括:

  • 理解基数字段语法。

  • 为具有基数字段部分的字段生成缺失的类型转换器。

  • 基于 parse-type 构建。

Regex 匹配器

它具有以下特性:

  • 向后兼容 Cucumber。

  • 比 parse 匹配器更易于使用。

让我们详细了解 parse 匹配器。

Parse 匹配器

特性文件中可能存在具有几乎相同短语的步骤。Behave 具有解析能力。为此使用use_step_parser方法,我们必须将解析器类型作为参数传递给该方法。

对于 parse 匹配器,我们必须传递参数 parse。它利用 parse 进行正则表达式解析和匹配。

特性文件(几乎相同的 Given 步骤)

类似步骤的特性文件如下所示:

Feature − Payment Process
Scenario − Check Debit transactions
      Given user is on "debit" screen
      When user makes a payment
Scenario − Check Credit transactions
      Given user is on "credit" screen

对应的步骤实现文件

步骤实现文件如下所示:

from behave import *
#define parser type
use_step_matcher("parse")
@given('user is on "{p}" screen')
def step_impl(context, p):
   print(p)
@when('user makes a payment')
def step_pay_complete(context):
   pass

输出

运行特性文件后获得的输出如下所示。在这里,我们使用了命令behave --no-capture -f plain

Step Matchers

输出显示debitcredit。这两个值已通过特性文件中几乎相同的 Given 步骤传递。在步骤实现中,我们已经解析了这两个步骤。

Behave - 正则表达式

让我们总体了解正则表达式的语法:

  • 点 (.) - 等效于任何字符。

  • 插入符号 (^) - 等效于字符串的开头。(^…)

  • 美元符号 ($) - 等效于字符串的结尾。(…$)

  • | - 表达式 x|y,匹配 x 或 y。

  • \ - 转义字符。

  • \. - 匹配点 (.)

  • \\ - 匹配反斜杠 (\)

  • [...] - 声明一组字符。([A-Za-z])

  • \d - 匹配数字。([0-9])

  • \D - 匹配非数字。

  • \s - 匹配空格字符。

  • \S - 匹配非空格字符。

  • \w - 匹配字母数字。

  • \W - 匹配非字母数字。

  • (...) - 对正则表达式的模式进行分组。

  • \number - 通过索引匹配先前组的文本。(\1)

  • (?P...) - 匹配模式并将其存储在 name 参数中。

  • (?P=name) - 匹配先前组名称匹配的所有文本。

  • (?:...) - 匹配模式,但无法捕获文本。

  • (?#...) - 注释(不考虑)。叙述模式的细节。

如果字符、字符集或组需要重复多次,则必须提供正则表达式模式的基数。

  • ? : 基数为 0...1 的模式:非必需(问号)

  • * : 基数为 0 或更多的模式,0..(星号)

  • + : 基数为 1 或更多的模式,1..(加号)

  • {n}:匹配 n 次重复的模式。

  • {a,b}:匹配模式从 a 到 b 次重复。

  • [A-Za-z]+ : 匹配多个字母字符。

特性文件(Feature File)中可能存在具有几乎相同短语的步骤。Behave 具有解析能力。为此,使用 `use_step_parser` 方法,并且必须将解析器类型作为参数传递给该方法。

对于正则表达式匹配器,必须传递参数 `re`。参数 `(?P...)` 用于从步骤定义中获取参数。

特性文件(几乎相同的步骤)

包含相似步骤的特性文件如下所示:

Feature − Payment Process
Scenario − Check Debit transactions
      Given user is on "debit" screen
   Scenario − Check Credit transactions
      Given user is on "credit" screen

对应的步骤实现文件

步骤实现文件如下所示:

from behave import *
#define parser type
use_step_matcher("re")
#regular expression parsing
@given('user is on "(?P<payment>.*)" screen')
def step_impl(context, payment):
   print("Screen type: ")
   print(payment)

输出

运行特性文件后获得的输出如下所示。这里,我们使用了命令 `behave --no-capture -f plain`。

Regular Expressions

输出显示借方和贷方。这两个值已通过特性文件中几乎相同的步骤传递。在步骤实现中,我们使用正则表达式解析了这两个步骤。

Behave - 可选部分

特性文件可能包含具有几乎相同短语的步骤。Behave 具有解析能力,因此一个步骤定义可以涵盖这些步骤。为此,使用 `use_step_parser` 方法,并且必须将解析器类型作为参数传递给该方法。

对于扩展的解析匹配器,必须传递参数 `cfparse`。它具有基数字段 (CF) 支持。默认情况下,它会为连接的基数生成缺失的类型转换器(如果给出了基数等于一的类型转换器)。

它可以支持以下解析表达式:

  • `{values:Type+}` – 基数 = 1..N,多

  • `{values:Type*}` – 基数 = 0..N,多0

  • `{values:Type?}` – 基数 = 0..1,可选

特性文件(几乎相同的步骤)

包含几乎相同步骤的特性文件如下所示:

Feature − Payment Process
Scenario − Check Debit transactions
      Given user is on "debit" screen
   Scenario − Check Credit transactions
      Given user is on "credit" screen

`register_type` 方法用于注册用户自定义类型,该类型可以在匹配步骤时用于任何类型转换。

对应的步骤实现文件

步骤实现文件如下所示:

from behave import *
import parse
#define parse type
use_step_matcher("cfparse")
# for whitespace characters
@parse.with_pattern(r"x\s+")
def parse_string(s):
#type converter for "x" succeeded by single/multiple spaces
   return s.strip()
#register user-defined datatype
register_type(x_=parse_string)
#optional part :x_? cardinality field in parse expression
@given('user is on {:x_?}{payment} screen')
def step_payment(context, x_, payment):
   print("Payment type: ")
   print(payment)

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

Optional Part

输出显示 `debit` 和 `credit`。这两个值已通过特性文件中几乎相同的步骤传递。在步骤实现中,我们使用解析表达式中的基数字段解析了这两个步骤。

Behave - 多方法

特性文件可能包含具有几乎相同短语的步骤。例如:

Given user makes payment of 100 INR
And user makes payment of 10 Dollar

这里,我们可以使用不同的步骤定义来区分印度卢比和美元。为此,我们可以使用多方法法,其中必须为不同的数据类型使用不同的正则表达式。

特性文件(几乎相同的步骤)

特性文件如下所示:

Feature − Multi-Methods
   Scenario − Purchase
      Given User is on shop
      When user purchases 3 shirts
      And user purchases 4 pants

在步骤实现文件中,`TypeBuilder.make_choice` 函数会评估为提供的选项提供的正则表达式模式。`register_type` 方法用于注册用户自定义类型,该类型可以在匹配步骤时用于任何类型转换。

此外,我们还应传递参数:用“{}”括起来的用户自定义数据类型。

对应的步骤实现文件

步骤实现文件如下所示:

from behave import *
from behave import register_type
from parse_type import TypeBuilder
parse_dress = TypeBuilder.make_choice(["shirts", "t-shirts"])
#register user-defined datatype
register_type(Dress=parse_dress)
parse_pant = TypeBuilder.make_choice(["pants", "gowns"])
#register user-defined datatype
register_type(Pant=parse_pant)
@given("User is on shop")
def step_user_shop(context):
      pass
# multiple methods being used .
@when(u"user purchases {count:n} {d:Dress}")
def step_dress(context, count, d):
      print("User purchased: ")
      print(d)
      print("Count is:")
      print(count)
@when(u"user purchases {count:n} {p:Pant}")
def step_pant(context, count, p):
      print("User purchased: ")
      print(p)
      print("Count is:")
      print(count)

输出

运行特性文件后获得的输出如下所示,使用的命令为behave --no-capture -f plain

Multi-Methods

输出显示购买的商品及其数量。这两个值已通过特性文件中几乎相同的步骤(但数据类型不同)传递。在步骤实现中,我们使用了多种方法来获取这些值。

Behave - 步骤函数

步骤函数是在 steps 目录中存在的 Python 文件中创建的。该目录中的每个 Python 文件(扩展名为 .py)都会被导入以获取步骤实现。

一旦特性文件被触发执行,实现文件就会被加载。步骤函数与步骤装饰器相关联。

步骤实现必须以导入开头,使用以下命令:

from behave import *

这将导入 Behave 中描述的多个装饰器,以帮助我们找到步骤函数。`given`、`when`、`then` 等装饰器接受一个字符串参数。

例如,考虑以下代码:

@given('user is on admin screen')
def step_impl(context):
      pass

上述代码将匹配以下特性文件的 Given 步骤:

Feature − Admin Module
Scenario − Admin verification
      Given user is on admin screen

特性文件中以 And/But 开头的步骤将重命名为其之前的步骤关键字。

例如,考虑以下特性文件:

Feature − Admin Module
Scenario − Admin verification
      Given user is on admin screen
       And user is on history screen
       Then user should be able to see admin name
         But user should not able to check history

And 步骤将重命名为 Given 步骤,But 步骤将重命名为之前的步骤关键字。所有这些都在内部处理。

如果连续有多个 And/But 步骤,它们将继承非 And 或 But 关键字的关键字。

具有步骤装饰器的步骤函数至少应包含一个参数。第一个参数称为上下文变量。其他参数来自步骤参数(如果需要)。

例如,请参考根据步骤参数的步骤函数。

@given('user is on admin screen')
def step_impl(context):
      pass

项目结构

特性文件的项目结构如下所示:

Step Functions

Behave - 步骤参数

我们可以在步骤名称中使用参数。这些参数可以使用正则表达式或使用 `use_step_matcher` 方法的默认或扩展解析器来处理。

`behave.use_step_matcher(name)`

修改解析步骤文本的参数匹配器。Behave 中存在多个内置解析器,如下所述:

  • `parse` – 它提供了一个简单的解析器,该解析器使用简单的语法恢复步骤参数的正则表达式。例如,`{parameter: type}`。它允许使用类型转换器进行类型转换。

  • `cfparse` – 它具有基数字段 (CF) 支持。默认情况下,它会为连接的基数生成缺失的类型转换器(如果给出了基数等于一的类型转换器)。它可以支持以下解析表达式:

    `{values:Type+}` – 基数 = 1..N,多

    `{values:Type*}` – 基数 = 0..N,多0

    `{values:Type?}` – 基数 = 0..1,可选

    它允许使用类型转换器进行类型转换。

  • `re` – 它使用完整的正则表达式来解析子句。我们必须借助命名组 `(?P...)` 来声明从文本中获得的变量,然后将其馈送到步骤 ()。

我们可以使用 `register_type` 方法创建自定义匹配器和新的数据类型。

`behave.register_type(w)`

注册用户自定义类型,以便在步骤匹配时进行类型转换期间进行解析。

`class behave.matchers.Matcher(func, pattern ,step_type=None)`

它从步骤名称中提取参数。

  • `pattern` – 与步骤函数关联的模式匹配。

  • `func` – 步骤函数与模式关联。

  • `check_match(step)` – 与提供的步骤名称匹配。

  • `describe(schema=None)` – 以文本形式提供函数或匹配器对象的描述。

  • `regex_pattern`:产生使用的文本正则表达式。

`class behave.model_core.Argument(start, end, original, value, name=Name)`

特性文件中使用步骤装饰器参数获得的步骤名称的参数。

属性如下:

  • `original` – 在步骤名称中匹配的原始文本。

  • `value` – 已进行类型转换的参数值。

  • `name` – 参数名称。如果未给出参数,则值为 None。

  • `start` – 参数在步骤名称中的起始索引。

  • `end` – 参数在步骤名称中的结束索引。

`class behave.matchers.Match(func, arguments=None)`

特性文件中已进行参数匹配并使用步骤装饰器参数获得的步骤。

属性如下:

  • `func` – 适用于给定匹配的步骤函数。

  • `arguments` – 参数列表,其中包含从步骤名称中获得的匹配参数实例。

Behave - 运行脚本

我们可以通过运行命令行参数运行 Behave 测试,或者我们可以创建一个运行器脚本。此脚本提供运行测试并生成相应报告的功能。

我们可以重试并执行失败的测试。此外,在执行整个套件之前,运行器脚本能够进行应用程序编程接口 (API) 调用并确保 API 没有问题。

运行器脚本步骤

按照以下步骤在 Behave 中成功创建和执行运行器脚本。

步骤 1 - 在 features 文件夹中创建一个运行器脚本 (runner.py)。

您的计算机上将出现以下屏幕:

Steps for Runner Script

步骤 2 - 运行测试的运行器脚本实现

可以使用以下代码实现运行测试的运行器脚本:

import subprocess
if __name__ == '__main__':
#command line args along with error capture on failure with check true
      s = subprocess.run('behave --no-capture',shell=True, check=True)

步骤 3 - 执行运行器脚本

使用命令 `python3 runner.py`(如果 Python 版本为 3)执行 runner.py 文件。您的计算机上将出现以下屏幕

Execute the Runner Script

步骤 4 - 通过传递命令行参数来参数化运行器脚本。

运行测试的运行器脚本实现可以如下完成:

import argparse
import subprocess
if __name__ == '__main__':
   p = argparse.ArgumentParser()
  #--testdir command line argument added
   p.add_argument('--testdir', required=False, help="File path")
   a = p.parse_args()
   testdir = a.testdir
   #complete command
   c= f'behave --no-capture {testdir}'
   s = subprocess.run(c, shell=True, check=True)

步骤 5 - 执行运行器脚本

使用命令 `python3 runner.py --testdir=features` 执行 runner.py 文件。

Python3 Runner

Behave - 排除测试

我们可以通过文件名排除要执行的文件。

假设 features 文件夹中有多个特性文件。计算机上可以看到以下屏幕:

Exclude Tests

执行命令 behave 后,输出将如下所示:

Payment Feature

如果我们只需要运行特性文件 `Payment.feature` 并排除 `Payment1.feature`,则必须传递命令行参数 `--e` 或 `--exclude`,后跟正则表达式的模式。

执行命令 `behave --exclude *1.feature` 后,输出如下所示:

Executing

输出显示 `一个特性通过` 以及 `Payment.feature` 文件名。此外,Payment1.feature 未包含在运行中。

Behave - 重试机制

我们可以在 Behave 中重新运行特性文件中失败的场景。这由格式化程序处理。

可以使用以下命令查看 Behave 中所有可用的格式化程序:

behave –f help

使用该命令后,您可以看到以下屏幕:

Retry Mechanism

重新运行格式化程序用于捕获失败的场景并将其输出到单独的文件中。让我们来看一个例子,其中我们有一个失败的特性。

Rerun Formatter

然后使用以下命令捕获另一个特性文件中的失败特性:

behave –f rerun –o failed_features.feature

您可以看到以下内容:

virtualbox

`failed_features.feature` 文件在项目中生成。它包含我们发生失败的特性文件名称 `Payment1.feature`。

Feature file with the command

要仅重新触发失败的场景,我们必须运行以下命令:

behave @failed_features.feature

您将看到以下屏幕:

Re-trigger only Failed Scenario

Behave - 报告

报告生成是测试自动化框架最重要的步骤之一。执行结束时,我们不能依赖控制台输出,而应该有一个详细的报告。

它应包含有关通过、失败、跳过、特性和场景细分的测试数量的信息。Behave 不会生成内置报告,但它可以输出多种格式,我们可以利用第三方工具生成报告。

可以使用以下命令显示 Behave 中所有可用的格式化程序:

behave --format help

使用该命令后,您的计算机上将出现以下屏幕:

Reports

一些常见的 Behave 报告包括:

  • Allure 报告。

  • 输出 JSON 报告。

  • JUnit 报告

JUnit 报告

让我们执行一个包含两个特性文件的测试,测试结果如下:

JUnit Report

上述测试的项目文件夹结构如下所示:

Project Folder Structure

步骤 1 - 执行命令

要创建 JUnit 报告,请运行以下命令:

behave --junit 

步骤 2 - 生成报告文件夹

项目中会生成一个名为 reports 的文件夹,其中包含名为 TESTS-<feature 文件名>.xml 的文件。

Report Folder Generation

这里,Payment 和 Payment1 是 feature 文件的名称。

步骤 3 - 将报告生成到特定文件夹

要将报告生成到特定文件夹(例如 my_reports),我们必须运行以下命令:

behave --junit --junit-directory my_reports
Specific Folder

项目中会生成一个名为 my_reports 的文件夹,其中包含报告。

JSON 报告

我们可以创建 Behave JSON 报告。JSON 实际上是一个格式化程序。

让我们执行一个包含两个特性文件的测试,测试结果如下:

Feature Passed

上述测试的项目文件夹结构如下:

Structure

步骤 1 - 执行命令

要在控制台中创建 JSON 输出,请运行以下命令:

behave -f json

将出现以下屏幕:

Console

步骤 2 - 以易于阅读的格式输出

要以更易于阅读的格式创建 JSON 输出,请运行以下命令:

behave -f json.pretty

下面图片中捕获了部分输出:

Json Pretty

步骤 3 - 将报告生成到特定文件夹

要将报告生成到特定文件夹(例如 my_reports.json),我们必须运行以下命令:

behave –f json.pretty –o my_reports.json

下图显示了您计算机上将出现的屏幕。

My Reports Json

项目中会生成一个名为 my_reports.json 的文件夹,其中包含所有已执行功能的详细信息。

Allure 报告

要在 Behave 中生成 Allure 报告,我们首先必须在系统中安装 Allure。要在 Linux 的命令行中进行安装,请按顺序运行以下命令:

sudo apt-add-repository ppa:qameta/allure
sudo apt-get update
sudo apt-get install allure

对于 Mac 用户,可以使用 Homebrew 通过以下命令进行安装:

brew install allure

对于 Windows,Allure 通过 Scoop 安装程序安装。运行以下命令下载并安装 Scoop,最后在 PowerShell 中执行:

scoop install allure

要更新 Scoop 中 Allure 发行版的安装,请从 Scoop 的安装目录运行以下命令:

\bin\checkver.ps1 allure -u

最后,运行以下命令:

scoop update allure

安装 Allure 后,我们必须获取 Python 的 Allure-Behave 集成插件。为此,请运行以下命令:

pip install allure-behave

要验证 Allure 是否已成功安装,请运行以下命令:

allure

让我们执行一个包含两个特性文件的测试,测试结果如下:

Execute a Test

上述测试的项目文件夹结构如下:

My Allure

步骤 1 - 将报告生成到特定文件夹

要将报告生成到特定文件夹(例如 my_allure),我们必须运行以下命令:

behave -f allure_behave.formatter:AllureFormatter –o my_allure

您将看到如下所示的屏幕:

JSON Extension

项目中会生成一个名为 my_allure 的文件夹,其中包含扩展名为 .json 的文件。

步骤 2 - 启动 Web 服务器

要启动 Web 服务器,请运行以下命令:

allure serve my_allure

这里,my_allure 是包含 allure json 文件的目录。

Allure JSON Files

同时,浏览器会打开,显示如下所示的 Allure 报告:

Allure Report

我们还可以点击单个功能并找到它们的细分,如下所示:

Allure Behaviors

Behave - 钩子

Behave 的 setup 和 teardown 函数在一个名为 environment.py 的文件中实现,该文件与包含 steps 文件夹的同一目录中。

setup 函数包括:打开浏览器、数据库连接、配置等等。

teardown 函数包括:关闭浏览器、终止数据库连接、撤销更改等等。

  • environment.py 文件包含以下函数:

  • before_feature(context, feature) - 在每个功能之前执行。

  • before_scenario(context, scenario) - 在每个场景之前执行。

  • before_step(context, step) - 在每个步骤之前执行。

  • before_tag(context, tag) - 在每个标签之前执行。

  • before_all(context) - 在所有内容之前执行。

  • after_feature(context, feature) - 在每个功能之后执行。

  • after_scenario(context, scenario) - 在每个场景之后执行。

  • after_step(context, step) - 在每个步骤之后执行。

  • after_tag(context, tag) - 在每个标签之后执行。

after_all(context) - 在所有内容之后执行。

Project Structure

以上函数用作 Behave 中的钩子。项目结构应如下所示:

包含钩子的 Feature 文件 (Payment.feature)

Feature − Payment Process
Scenario − Verify transactions
         Given user makes a payment of 100 INR And user makes a payment of 10 Dollar

包含 Payment.feature 钩子的 feature 文件如下:

包含钩子的 Feature 文件 (Payment1.feature)

Feature − Administration Process
Scenario − Verify admin transactions
         Given user is on admin screen

包含 Payment1.feature 钩子的 feature 文件如下:

步骤实现文件如下所示:

from behave import *
from parse_type import TypeBuilder
parse_amt = TypeBuilder.make_choice(["100", "10"])
register_type(Amt=parse_amt)
parse_curr = TypeBuilder.make_choice(["INR", "Dollar"])
register_type(Curn=parse_curr)
@given("user makes a payment of {n:Amt} {t:Curn}")
def step_payment(context, n, t):
   pass
@given('user is on admin screen')
def step_admin(context):
   pass

相应的步骤实现文件

步骤 4 - environment.py 文件中的钩子

# before all
def before_all(context):
   print('Before all executed')
# before every scenario
def before_scenario(scenario, context):
   print('Before scenario executed')
# after every feature
def after_feature(scenario, context):
   print('After feature executed')
# after all
def after_all(context):
   print('After all executed')

输出

environment.py 文件中的钩子如下:

Hooks

Behave - 调试

运行 feature 文件后获得的输出如下:

可以通过预运行测试步骤来调试 Behave 脚本。预运行有助于检查所有测试步骤,而无需实际运行。它有助于确定步骤定义文件中的未定义步骤。

它验证是否存在任何缺少的导入语句、语法错误等等。通过预运行,所有这些问题都会很快被检测到。如果我们正在进行批量更新或任何配置更改,预运行有助于在短时间内检测任何错误。

behave --no-capture --dry-run

您将看到如下所示的屏幕:

Debugging

如果我们必须运行整个套件进行调试,那将非常耗时。在 Behave 中,我们可以通过以下命令进行预运行调试:

输出显示 3 个未测试,显示测试步骤的数量。

Three Untested

让我们预运行包含未实现步骤的 feature 文件,如下所示:

打印页面
© . All rights reserved.