Behave 简明教程

Behave - Quick Guide

Behave - Introduction

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

简而言之,技术人员和非技术人员都在整个项目中扮演着角色。Behave 的测试使用纯文本编写,并且在 Python 中实现逻辑。

BDD 格式从软件特征的描述开始,类似于一个故事。

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

  1. 为特征开发一个失败的测试用例。

  2. 实现一个测试通过的逻辑。

  3. 代码优化以满足项目指南。

BDD 有大量库,例如支持 JavaScript 的 Mocha、支持 Java/Ruby 的 Cucumber 和支持 Python 的 Behave 等。

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

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

Feature File

Behave 中的功能文件可以如下所示 −

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

Corresponding step definition file

以下是 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')

Output

obtained after running the feature file 的输出如下 −

behaviour driven development

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

Behave - Installation

行为安装可以通过以下方式来完成 −

With pip

对于行为安装,我们应该为我们的系统安装 Python 语言 pip – the package installer 。如果 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

With Source Distribution

在解压 Behave 的源代码包之后,输入新生成的目录 'behave-<version>' ,然后执行下面提到的命令——

python setup.py install

With Git Repository

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

然后,使用 Git 仓库安装最新版本的 Behave,运行下面提到的命令——

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

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

Behave - Command Line

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

Command Line Arguments

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

  1. –c, --no-color

损害 ANSI 彩色转义的使用。

  1. --color -

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

  1. –d, --dry-run

在不运行步骤的情况下调用格式化程序。

  1. -D, --define

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

  1. –e, --exclude Pattern

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

  1. –i, --include Pattern

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

  1. --no-junit

不输出 JUnit 报告。

  1. --junit

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

  1. –f, --format

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

  1. -steps-catalog

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

  1. –k, --no-skipped

不将被跳过的步骤打印到控制台中。

  1. no-snippets

不将尚未实现的步骤片段打印到控制台中。

  1. --snippets

在控制台中打印时包含片段,其中包括尚未实施的步骤。这是内置特性,可覆盖配置文件设置。

  1. –m, --no-multiline

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

  1. --multiline

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

  1. –n, --name

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

  1. --no-capture

排除将 stdout 捕获。

  1. --capture

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

  1. --no-capture-stderr

排除将 stderr 捕获。

  1. --capture-stderr

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

  1. --no-logcapture

排除将日志捕获。

  1. --logcapture

包含日志捕获。在故障期间,将出现和提供步骤的每一份日志。这是内置特性,可覆盖配置文件设置。

  1. --logging-level

提及应捕获的日志级别。默认值为 INFO。

  1. --logging-format

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

  1. --logging-datefmt

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

  1. --logging-filter

提及是否对语句进行过滤。默认会捕获所有语句。如果输出过长,我们可以利用该选项来过滤掉不必要的输出。

  1. --logging-clear-handlers

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

  1. --no-summary

排除执行后的摘要。

  1. -summary

包含执行后的摘要。

  1. –o, --outfile

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

  1. –q, --quiet

别名用于 –no-snippets –no-source。

  1. –s, --no-source

不包括打印文件和步骤定义行和步骤。

  1. --show-source

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

  1. --stage

  2. --stop

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

  1. –t, --tags

包括具有标记的特性/场景,这些标记与执行中的 TAG_EXPRESSION 相同。

  1. –T, --no-timings

不包括打印每个步骤的执行持续时间。

  1. --show-timings

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

  1. –v, --verbose

显示加载的特性和文件。

  1. –w, --wip

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

  1. –x, --expand

展平输出中场景提纲的表格。

  1. --lang

使用英语之外的语言的关键字。

  1. --lang-list

显示所有可用语言 –lang。

  1. --lang-help

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

  1. --tags-help

显示标记语句的帮助信息。

  1. --version

显示版本。

  1. junit –directory

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

  1. --show-skipped

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

Behave - Configuration Files

Behave 配置文件称为 .behaverc / behave.ini / setup.cfg / tox.ini (可选择一个并根据用户选择设定)。

文件可以位于以下位置−

  1. The present working directory.

  2. User home directory.

  3. 对于 Windows 用户,在目录 %APPDATA% 中。

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

例如,

[behave]
format = plain
dry_run = false

Types of Parameters

Behave 中的配置参数类型包括以下内容−

  1. Text − 将文本分配给配置设置。

  2. Bool − 将布尔值分配给配置设置。文本定义行为(真值包括 1、true、yes 和 on)。假值包括 0、false、no 和 off)。

  3. Sequence&lt;text&gt; − 接受新行上的多个值。

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

tags=@a, ~@b
         @c

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

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

Configuration Parameters

Behave 中的一些配置参数如下−

  1. color − bool

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

  1. dry_run − bool

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

  1. userdata_defines − sequence<text>

声明用于 config.userdata 词典的自定义数据。

  1. exclude_re − text

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

  1. include_re − text

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

  1. junit − bool

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

  1. junit_directory − text

这是存储 JUnit 报表的位置。

  1. default_format − text

声明默认格式。默认值为 pretty。

  1. format: sequence<text>

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

  1. steps_catalog − bool

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

  1. scenario_outline_annotation_schema: text

提及场景大纲的注释模式。

  1. show_skipped − bool

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

  1. show_snippets − bool

在控制台打印时包括尚未实现的步骤的代码段。这是内置特性,并且可以覆盖配置文件设置。

  1. show_multiline − bool

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

  1. name − sequence<text>

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

  1. stdout_capture − bool

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

  1. stderr_capture − bool

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

  1. log_capture − bool

包含日志捕获。在故障期间,将出现和提供步骤的每一份日志。这是内置特性,可覆盖配置文件设置。

  1. logging_level − text

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

  1. logging_format − text

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

  1. logging_datefmt − text

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

  1. logging_filter − text

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

  1. logging_clear_handlers : bool

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

  1. summary − bool

执行后包括一个摘要。

  1. outfiles − sequence<text>

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

  1. paths − sequence<text>

提及特性的文件默认路径。

  1. quiet − bool

别名用于 –no-snippets –no-source。

  1. show-source − bool

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

  1. stage − text

描述测试的当前阶段。阶段名称用作环境文件的名称附加信息,以及步骤目录。

  1. stop − bool

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

  1. tags − sequence<text>

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

  1. default_tags − text

如果未给定默认标记,则声明默认标记。

  1. show_timings − bool

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

  1. verbose − bool

显示加载的特性和文件。

  1. wip − bool

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

  1. expand − bool

展平输出中场景提纲的表格。

  1. lang − text

使用英语之外的语言的关键字。

Behave - Feature Testing Setup

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

  1. 由业务分析员或任何项目相关人员创建的 Feature files ,其中包含与行为相关的用例。

  2. Step Implementation file 用于功能文件中定义的场景。

  3. Environment Setup files ,在其中,步骤、特性、场景等之前和之后要执行前提条件/后置条件。

Feature File

功能文件应该位于名为特性文件夹中。此外,特性目录中应该有一个名为步骤的子目录。

feature file

Launching Feature file

我们可以使用各种命令行参数启动特性文件。这些如下所述 −

  1. 如果没有可用的信息,将加载 features 目录中的所有特性文件以在 behave 中执行。

  2. 如果提供了功能目录的路径,那么功能目录中必须至少有一个功能文件(.feature 扩展名)和一个名为 steps 的子目录。

  3. 此外,如果 environment.py 存在,它应当位于具有 steps 目录的目录中,而不在 steps 目录中。

  4. 如果提供了指向功能文件的路径,那么它指示 Behave 搜索该文件。要获取该功能文件对应的步骤目录,需要搜索父目录。

  5. 如果没有在当前父目录中找到,则查找其父目录。当到达文件系统根目录时,此过程将继续。另外,如果 environment.py 存在,则它应位于包含 steps 目录(而不是 steps 目录内)的目录中。

Behave - Gherkin Keywords

行为中的 Gherkin 关键字列在下面 −

  1. Features

  2. Scenario

  3. Steps

  4. Background

  5. Scenario Outline

  6. Text

  7. Table

  8. Tags

  9. Given

  10. When

  11. Then

  12. But

  13. And

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

行尾结束语句包含在行为中。我们可以使用制表符/空格来缩进。大多数行均以 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 hook 执行之后。

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

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

不应将背景用于创建复杂状态(仅在不可避免时)。这段应简短且真实。此外,我们应该避免在一个功能文件中包含大量用例。

Feature File with 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 等开头。建议使用用例来检查单个特征或预期结果。

Feature File with 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

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

测试根据示例表中标题行内找到的每一行执行一次。要测试的值由括号 <> 中包含的名称表示。这些名称应与示例表标题匹配。

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

Feature File with Scenario Outline

具有用例大纲关键字的功能文件如下 -

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

Example

以下是具有用例大纲的功能文件示例 -

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

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

Given

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

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

Feature File with 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 开始的步骤用于添加用户要执行的重要任务。通过此步骤,用户可以与系统进行通信,从而更改系统的状态或影响其他地方。

Feature File with 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 步骤用于数据库场景,因为它本质上用于描述最终用户可注意的后果。

Feature File with 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 步骤。它为用户提供了更好的可读性。

Feature File with multiple consecutive Then/Given steps

在 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

Feature File without multiple Then/Given steps

没有多个 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

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

列数据应使用 | 符号分隔。

Feature File with 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 的实例。

Implementation logic for Table

在 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

在 """ 中封闭的步骤后的文本块将与该步骤关联。在此处,会分析缩进。从文本中删除所有开头的空格。此外,所有后续行都必须至少有一个空格作为起始行。

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

Feature File with Text

使用 text 关键字的功能文件如下:

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 能够仅验证该功能文件的部分章节。只有场景、功能、场景大纲可以进行标记。

此外,用于功能的标记应由其所有的场景和大纲继承。标记放在我们要标记的场景或功能之前。我们还可以在一行内通过空格使用多个标记。一个标记以 @ 开头,后跟标记名称。

Feature File with tags

使用 tags 关键字的功能文件如下:

@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 - Feature Files

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

  1. Feature files 由业务分析师或任何项目利益相关者创建,并包含与行为相关的用例。

  2. Step Implementation file 用于功能文件中定义的场景。

  3. Environment Setup files 其中预/后置条件将在步骤、功能、场景等之前和之后执行。

功能文件应位于名为 features 的文件夹中。此外,features 目录中还应有子目录 steps。

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

features directory

Launching Feature file

我们可以使用各种命令行参数启动功能文件,如下所述——

  1. 如果没有可用的信息,features 目录中的所有功能文件都将被加载以在 Behave 中执行。

  2. 如果提供了功能目录的路径,那么功能目录中必须至少有一个功能文件(.feature 扩展名)和一个名为 steps 的子目录。

  3. 此外,如果 environment.py 存在,它应当位于具有 steps 目录的目录中,而不在 steps 目录中。

  4. 如果提供了指向功能文件的路径,那么它指示 Behave 搜索该文件。要获取该功能文件对应的步骤目录,需要搜索父目录。

  5. 如果在当前父目录中未找到,则搜索其父目录。这将一直持续到到达文件系统根目录为止。此外,如果 environment.py 存在,它应当位于具有 steps 目录的目录中,而不在 steps 目录中。

Structure of a Feature File

功能包括场景。场景可能包含也可能不包含说明、背景和一组标记。

功能文件结构如下 −

Feature File

功能文件格式如下 −

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

Corresponding Step Implementation File.

相应的步骤实现文件看起来像下面提到的文件 −

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')

Output

运行功能文件后获得的输出如下 −

feature and scenario names

输出显示功能和场景名称,以及测试结果和测试执行时间。

Behave - Step Implementations

Behave 中功能文件中的场景步骤应具有以 Python 编写的执行逻辑。这称为执行/步骤定义文件(.py 扩展名),应存在于 steps 目录中。

此文件中提供了所有必需的导入。步骤目录应成为特性目录的一部分。

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

step implementations

步骤定义文件包含定义特性文件中的步骤的 Python 函数。在 Python 函数的开头,必须具有以 @given、@when 等开头的修饰符。这些修饰符与功能文件中的给定、然后、何时和其他步骤进行比较和匹配。

Feature File

功能文件如下 −

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

Corresponding Step Implementation File

相应的步骤实现文件看起来像下面提到的文件 −

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')

Output

运行功能文件后获得的输出如下 −

corresponding step implementation file

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

Behave - First Steps

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

Feature File

标题为支付类型的功能文件的示例如下 −

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

Corresponding Step Implementation File

上述功能对应的步骤实现文件如下 −

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')

Project Structure

功能“支付类型”的项目结构如下 −

payment types

Output

运行功能文件后获得的输出如下,此处使用的命令为 behave

running the feature file

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

Python 控制台输出如下 −

python console

Behave - Supported Languages

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

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

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

supported languages

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

particular language

功能文件可以与特定语言相关联。此时,BDD 框架会选择该特定语言的关键词。该语言可以在配置文件中设置为默认值。

行为配置文件可以是 .behaverc 或 behave.ini 文件。如果我们想要语言为丹麦语,则该配置文件中的参数 lang 值应设置为 da。

Configuration file setup

为选择特定语言而设置的功能文件如下所示,用作示例的语言为丹麦语 (da)。

[behave]
lang = da

Behave - Step Parameters

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

Feature File

请考虑如下功能文件示例:

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

该功能文件包含几乎与 Given 和 And 步骤相同的步骤。唯一的区别在于白天和晚上的轮班时间。我们可以将参数传递给步骤定义文件中的步骤,而不必重复实现几乎相同的步骤。

请注意:我们将 day 和 night 参数放在双引号文本中(也可以使用单引号文本)放入功能文件中。在步骤实现中,我们将以 {} 括住传递参数。

此外,该参数作为带有实现方法的自变量之一传递。

Corresponding Step Implementation File

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

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

Output

运行功能文件后获得的输出如下,使用的命令是 behave --no-capture -f plain

step parameters

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

Behave - Scenario Outlines

如果我们有一组类似的条件并且结果要传递给场景,则可以使用场景提纲。场景提纲与示例表一起使用。场景提纲可以有多个示例表。

对于在示例表(接表头行之后)中找到的每一行,测试都将执行一次。要测试的值由括号<>中的名称表示。这些名称应与示例表头相匹配。

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

Feature File

场景大纲的功能文件如下−

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     |

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

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

Corresponding Step Implementation File

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

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

Output

在运行功能文件并使用 behave --no-capture -f plain 命令后,即可获得输出。

scenario outlines

输出显示 Username for login: user1, Password for login: pwd1 and Username for login: user2, Password for login: pwd2 已打印。此处,两个数据集已从“示例”传递。

Behave - Multiline Text

用 “””括起来的步骤后的文本块将与此步骤链接。此处,解析缩进。将从文本中删除开头的所有空格,并且所有后续行都必须至少有一个最小空格作为起始行。

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

Feature File

标题为用户信息的 feature 文件如下−

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

Corresponding Step Implementation File

该 feature 的相应步骤实现文件如下−

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

Output

运行该 feature 文件后获取的输出如下所示并且所使用的命令是 behave --no-capture -f plain

multiline text

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

Behave - Setup Table

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

列数据应使用 | 符号分隔。

Feature File with Table (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

一个表可以用 context 变量(在步骤函数中传递)中的 .table 属性访问实现的 Python 代码。(表的一个实例。我们可以使用设置表来帮助设置测试。

Python code

访问表(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)

Corresponding Step Implementation File(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

Project setup

在 Python 项目中设置的文件如下所示

project set up

Output

运行功能文件后获得的输出如下,使用的命令是 behave --no-capture -f plain

setup table

输出显示打印了 step up 表。

Behave - Steps in a Step

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

Feature File with Similar Steps

具有类似步骤的特性文件如下所示 -

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 方法完成。

Corresponding Step Implementation File

上面提到的特性文件对应的步骤实现文件如下 -

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')

Output

运行功能文件后获得的输出如下,使用的命令是 behave --no-capture -f plain

no capture

后续输出如下所示 −

scenario verify

输出显示情景验证的新用户可以通过执行情景验证新用户可以处理付款中的步骤来处理付款。

Behave - Background

Background 用于为一群步骤添加组。它接近一个场景。我们可以使用 Background 向多个场景添加一个上下文。它在每个特征的场景之前运行,但在执行之前的钩子之后运行。

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

可以添加 Background 描述,以便人类更好理解。它在特征文件中的只出现一次,并且必须在场景或场景大纲之前声明。

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

Feature File with Background

以下是标题为“payment process”的特征的包含 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

Corresponding Step Implementation File

该文件如下所示−

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')

Output

以下是运行特征文件后获得的输出,这里使用的命令为 behave --no-capture -f plain

feature file with background

后续输出如下所示 −

background

输出显示 Background 步骤(Given 启动应用程序和 Then 输入凭据)在每个场景之前运行了两次。

Behave - Data Types

Behave 中存在两种数据类型,即预定义和用户定义。让我们首先了解什么是预定义数据类型。

Pre-defined Data types

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

  1. w(类型为 str)- 下划线和字母。

  2. W(类型为 str)- 下划线和非字母。

  3. s(类型为 str)- 空白。

  4. S(类型为 str)- 非空白。

  5. d(类型为 int)- 数字。

  6. D(类型为 str)- 非数字。

  7. n(类型为 int)- 带千位分隔符的数字。

  8. %(类型为 float)- 百分比。(转换为值/100.0)

  9. f(类型为 float)- 定点数字。

  10. e(浮点型)−浮点数连同指数。

  11. g(浮点型)−数字格式。

  12. b(整型)−二进制数。

  13. (整型)−八进制数。

  14. x(整型)−十六进制数。

  15. ti(datetime 型)−ISO 8601 日期/时间格式的时间。

  16. te(datetime 型)−RFC 2822 电子邮件数据/时间格式的时间。

  17. tg(datetime 型)−Global 数据/时间格式的时间。

  18. ta(datetime 型)−US 数据/时间格式的时间。

  19. tc(datetime 型)−ctime() 数据/时间格式。

  20. th(datetime 型)−HTTP 日志数据/时间格式的时间。

  21. tt (of time type)

在步骤实现中,我们将传递以下参数:包含在“{}”中的数据类型。

Feature File with % data type

带有 % 数据类型的功能文件如下所示 −

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%     |

Corresponding Step Implementation File

文件如下所示 −

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)

Output

在运行功能文件并使用 behave --no-capture -f plain 命令后,即可获得输出。

pre defined data types

后续输出如下所示 −

data types

输出显示 0.8 和 0.9,它们是由 % 数据类型获得的,以表示从功能文件中传递的 80% 和 90% 的值。

User-defined Data types

Behave 还有用户定义的数据类型。register_type 方法用于注册一个用户自定义类型,该类型可在匹配步骤时进行任何类型转换的解析。

Feature File

标题为支付流程的功能文件如下−

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 方法用于注册用户自定义类型,该类型可以在匹配步骤时被解析为任何类型转换。

Corresponding Step Implementation File

文件如下所示 −

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)

Output

在运行功能文件并使用 behave --no-capture -f plain 命令后,即可获得输出。

user defined data types

后续输出如下所示 −

浮点数 0 值

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

Behave - Tags

功能文件的章节可以进行标记,以便 Behave 能够仅验证该功能文件的部分章节。只有场景、功能、场景大纲可以进行标记。

此外,用于功能的标签应被其所有场景和场景大纲继承。标签位于我们要标记的场景或功能之前。我们还可以在一行中用空格分隔多个标签。

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

Feature File with tags (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

因此, the Feature File with tags(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

Corresponding Step Implementation File

文件如下所示 −

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')

Output

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

no capture payment feature

输出显示两个场景通过,因为在功能文件中,有两个场景带有 payment 场景标签。

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

credit payment

输出显示两个场景通过,因为在功能文件中,有两个场景没有标记为 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 - Enumeration

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

我们可能需要具有以下特征的用户定义数据类型 −

  1. 必须匹配少量单词。

  2. 在测试执行前进行预定义值。

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

Feature File

考虑一个针对名为 payment process 的功能的功能文件,如下所示 −

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

在步骤实现文件中,TypeBuilder.make_enum 函数对提供的单词或字符串枚举求值为正则表达式模式。method register_type 用于注册一个用户定义类型,该类型可以在匹配步骤时被解析为任何类型转换。

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

Corresponding Step Implementation File

以下是针对上述功能的步骤实现文件 −

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)

Output

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

enumeration data type

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

Behave - Step Matchers

Behave 中有三种类型的 Step Matcher。它们如下所示 −

  1. ParseMatcher (parse) − 基于 parse 模块。

  2. extended ParseMatcher(cfparse) − 允许基数语法。

  3. RegexMatcher (re) − 基于用于匹配模式的正则表达式。

Parse matcher

内置的 step matcher 具有以下所述特性:

  1. 使用和理解简单。

  2. 预定义和用户定义的数据类型支持此匹配器。

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

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

extended Parse matcher

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

其他特性包括 −

  1. 理解基数字段语法。

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

  3. Built on parse-type.

Regex matcher

它具有以下特性 −

  1. Backward compatible to Cucumber.

  2. 比起 parse 匹配器更易于使用。

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

Parse Matchers

功能文件中可能会有几乎具有类似短语的步骤。Behave 具有解析能力。方法 use_step_parser 用于此操作,我们必须将解析器类型作为参数传递给该方法。

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

Feature File (almost Given similar steps)

相似步骤的功能文件如下所示 −

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

Corresponding Step Implementation File

步骤实现文件如下所示 −

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

Output

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

step matchers

输出显示 debitcredit 。这两个值几乎与功能文件中的 Given 步骤类似而传递。在步骤实现中,我们解析了这两个步骤。

Behave - Regular Expressions

让我们对正则表达式的语法进行总体了解 −

  1. 点 (.) − 等效于任何字符。

  2. 脱字符号 (^) − 等效于字符串的开头。(^…)

  3. 美元符号 ($) − 等效于字符串的结尾。 (…$)

  4. | − 表达式 x| y,匹配 x 或 y。

  5. \ − Escape character.

  6. \. − 匹配点。 (.)

  7. \\ − 匹配反斜杠。 (\)

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

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

  10. \D − Matches non-digit.

  11. \s − 匹配空白字符。

  12. \S − 匹配非空白字符。

  13. \w − Matches alphanumeric.

  14. \W − Matches non-alphanumeric.

  15. (…) − 将正则表达式的模式分组。

  16. \number − 按照索引匹配前一组文本。(\1)

  17. (? P<name>…) − 匹配模式,并将它存储在 name 参数中。

  18. (?P=name) − 匹配所有与前一组 name 匹配的文本。

  19. (?:…) − 匹配模式,但无法捕获文本。

  20. (?#…​) − 注释(不被视为模式)。叙述模式的详细信息。

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

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

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

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

  4. {n}:为 n 次重复匹配一个模式。

  5. {a ,b}:为 a 至 b 次重复匹配一个模式。

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

功能文件中可能会有包含几乎相似短语的步骤。Behave 具有解析能力。为此使用了 use_step_parser 方法,我们必须将解析器类型作为参数传递给该方法。

对于正则表达式匹配器,我们必须传递参数 re。参数 (? P<name>…​) 用来从步骤定义获取参数。

Feature File (almost similar steps)

类似步骤的功能文件如下所示 −

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

Corresponding Step Implementation File

步骤实现文件如下所示 −

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)

Output

运行功能文件后获得的输出如下。在此,我们使用了命令 behave --no-capture -f plain

regular expressions

输出显示了借方和贷方。这两个值在功能文件中以几乎相似的步骤传递。在步骤执行中,我们使用正则表达式解析了两个步骤。

Behave - Optional Part

在 feature 文件中可能存在具有几乎相似短语的步骤。Behave 具有解析能力以便一个步骤定义可以涵盖这些步骤。为此使用 use_step_parser 方法,并且我们必须将解析器类型作为参数传递给该方法。

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

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

  1. {values:Type+} – Cardinality=1..N, many

  2. {values:Type*} – Cardinality=0..N, many0

  3. {values:Type?} – Cardinality=0..1, optional

Feature File (almost similar steps)

具有非常相似步骤的功能文件如下 −

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 方法用于注册用户定义的类型,以便在匹配步骤时可以对其进行任何类型转换的解析。

Corresponding Step Implementation File

步骤实现文件如下 −

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)

Output

运行功能文件后获得的输出如下,使用的命令是 behave --no-capture -f plain

optional part

输出显示 debitcredit 。这两个值通过特性文件中的几乎类似步骤来传递。在步骤实现中,我们在解析表达式的基数字段中解析了这两个步骤。

Behave - Multi-Methods

也许在功能文件中具有短语类似的步骤。例如,

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

在这里,我们可以有不同的步骤定义来区分 INR 和美元。为此,我们可以使用多方法方法,必须对不同的数据类型使用不同的正则表达式。

Feature File (almost similar steps)

将功能文件视为如下内容:

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 方法用于注册用户自定义类型,该类型可以在步骤匹配时解析为任何类型转换。

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

Corresponding Step Implementation File

步骤实现文件如下所示 −

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)

Output

运行功能文件后获得的输出如下,使用的命令是 behave --no-capture -f plain

multi methods

输出显示购买项目及其数量。在功能文件中几乎使用类似的步骤(但不同的数据类型)传递了这两个值。在步骤实现中,我们使用多种方法来获取值。

Behave - Step Functions

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

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

步骤实现必须从导入开始,使用下面提到的命令 -

from behave import *

这将导入 Behave 中描述的多个装饰器,帮助我们找到步骤函数。给定、当、然后等装饰器接受一个字符串参数。

例如,考虑下面给出的代码 -

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

上述代码将与下面特性文件中的 Given 步骤匹配,如下所示 -

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

特性文件中以且/但是开头的步骤被重命名为它们早期的步骤关键字。

例如,考虑下面给出的特性文件 -

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

且步骤将被重命名为给定步骤,而但是步骤将被重命名为早期的步骤关键字。所有这些都在内部处理。

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

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

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

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

Project Structure

功能的项目结构如下:

step functions

Behave - Step Parameters

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

behave.use_step_matcher(name)

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

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

  2. cfparse − 它支持基数字段 (CF)。默认情况下,它会为连接基数生成缺失的类型转换器(如果给出了基数等于一的类型转换器)。它可以支持以下解析表达式 -{values:Type+} – Cardinality=1..N、many{values:Type*} – Cardinality=0..N、many0{values:Type?} – Cardinality=0..1,可选 它允许使用类型转换器进行类型转换。

  3. re − 它利用完整的正则表达式来解析从句。我们必须借助命名组 (? P<name>…) 声明从文本中获取的变量,然后将其提供给步骤 ()。

我们借助 register_type 方法可以对自定义匹配器以及新数据类型进行注册。

behave.register_type(w)

在步骤匹配时,为类型转换期间解析注册用户定义的类型。

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

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

  1. pattern − 与步骤函数关联的模式匹配。

  2. func − 步骤函数与模式关联。

  3. check_match(step) − 与提供的步骤名称匹配。

  4. describe(schema=None) − 以函数或匹配器对象的文本形式给出描述。

  5. regex_pattern: 产生所利用的文本正则表达式。

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

带步骤装饰器参数的功能文件中步骤名称的参数。

属性如下 -

  1. original − 步骤名称中匹配到的原始文本。

  2. value − 经过类型转换的参数值。

  3. name − 参数名称。如果未提供参数,则值将设为 None。

  4. start − 参数在步骤名称中的起始索引。

  5. end − 参数在步骤名称中的结束索引。

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

特征文件中与参数匹配并使用步骤装饰器参数获取的一个步骤。

属性如下 -

  1. func − 适用于给定匹配的步骤函数。

  2. arguments − 获取步骤名称中的匹配的参数的实例的参数列表。

Behave - Runner Script

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

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

Steps for Runner Script

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

Step 1 − Create a runner script (runner.py) within the features folder.

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

steps for runner script

Step 2 − Runner Script Implementation to run tests

runner 脚本可以通过使用以下代码来实现以运行测试:

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)

Step 3 − Execute the runner script

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

execute the runner script

Step 4 − Parametrise runner script by passing command line arguments.

可以使用以下内容,作为 runner 脚本的实现来运行测试:

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)

Step 5 − Execute the runner script

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

python3 runner

Behave - Exclude Tests

我们可以通过其文件名从执行中排除正在执行的文件。

假设我们具有 features 文件夹中有多个功能文件。可以在计算机上看到以下屏幕:

exclude tests

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

payment feature

如果我们仅运行 Payment.feature 功能文件并排除 Payment1.feature ,我们必须传递命令行参数 --e--exclude 后跟正则表达式的模式。

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

executing

输出显示 one feature passed 以及 Payment.feature 文件名。此外,Payment1.feature 不包含在运行中。

Behave - Retry Mechanism

我们可以在 Behave 中重新运行功能文件中的失败场景。这是在格式化程序的帮助下进行的。

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

behave –f help

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

retry mechanism

rerun 格式化程序用于捕获失败的场景,并将其输出到一个单独的文件中。让我们举一个例子,其中我们有 1 个失败的功能。

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 - Reports

报告生成是朝着测试自动化框架迈出的最重要的步骤之一。在执行结束时,我们无法依赖控制台输出,而是应该提供一份详细的报告。

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

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

behave --format help

当您使用该命令时,您的电脑上将出现以下屏幕:

reports

一些常见的 Behave 报告为:

  1. Allure Report.

  2. Output JSON Report.

  3. JUnit Report

JUnit Report

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

junit report

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

project folder structure

Step 1 − Execute the command

要创建一个 JUnit 报告,请运行下面给出的命令:

behave --junit

Step 2 − Report folder generation

将在项目中生成一个名为 reports 的文件夹,名称为 TESTS-<feature file name>.xml

report folder generation

此处,Payment 和 Payment1 是特性文件名称。

Step 3 − Report generation to a specific folder

要将报告生成到一个特定文件夹(比如 my_reports),我们需要运行下面提到的命令:

behave --junit --junit-directory my_reports
specific folder

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

JSON Report

我们可以创建行为 JSON 报告。JSON 实际上是一种格式化器。

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

feature passed

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

structure

Step 1 − Execute the command

要在控制台中创建 JSON 输出,运行命令−

behave -f json

将出现以下屏幕−

console

Step 2 − Output in readable format

要以更易读的格式创建 JSON 输出,运行以下命令−

behave -f json.pretty

以下是捕获在下图中一部分输出−

json pretty

Step 3 − Report generation to a specific folder

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

behave –f json.pretty –o my_reports.json

下图表示将出现在您计算机上的屏幕。

my reports json

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

Allure Report

要在 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

Step 1 − Report generation to a specific folder

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

behave -f allure_behave.formatter:AllureFormatter –o my_allure

你会得到如下所示的屏幕——

json extension

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

Step 2 − Start the web server

要启动 Web 服务器,运行以下给出的命令:

allure serve my_allure

这里,my_ allure 是包含 allure JSON 文件的目录。

allure json files

同时,打开一个浏览器,其中包含如下所示的 Allure 报告:

allure report

我们还可以点击各个 feature 并找到它们的分解,如下所示:

allure
behaviors

Behave - Hooks

Behave 设置和取消设置函数在名为 environment.py 的文件中实现,该文件位于包含 steps 文件夹的同一目录中。设置函数包括 - 浏览器打开、数据库连接、配置等。

取消设置函数包括浏览器关闭、数据库连接终止、还原更改等。

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

  1. before_feature(context,feature) - 在每个 feature 之前执行。

  2. before_scenario(context,scenario) - 在每个 scenario 之前执行。

  3. before_step(context,step) - 在每个 step 之前执行。

  4. before_tag(context,tag) - 在每个 tag 之前执行。

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

  6. after_feature(context,feature) - 在每个 feature 之后执行。

  7. after_scenario(context,scenario) - 在每个 scenario 之后执行。

  8. after_step(context,step) - 在每个 step 之后执行。

  9. after_tag(context,tag) - 在每个 tag 之后执行。

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

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

project structure

Feature File with hooks (Payment.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

Feature File with hooks (Payment1.feature)

下面给出带有钩子的 Payment1.feature 的功能文件 −

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

Corresponding step Implementation File

步骤实现文件如下所示 −

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

Step 4 − Hooks in environment.py file

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')

Output

运行功能文件后获得的输出如下 −

hooks

Behave - Debugging

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

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

如果我们不得不运行整个套件进行调试,那将非常耗时。在 Behave 中,我们可以使用下面提到的命令通过预运行进行调试——

behave --no-capture --dry-run

你会得到如下所示的屏幕——

debugging

输出显示了 3 untested ,其中显示了测试步骤的数量。

让我们预运行具有未实现步骤的功能文件,如下所示——

three untested

输出明确定义了通过预运行在步骤定义文件中获得的未定义步骤。