使用 Behat 和 Gherkin 应用 BDD

为了帮助我们轻松理解什么是 BDD 以及如何使用 BDD,我们将尝试将其应用于项目中的示例场景。回顾 第 2 章 "理解和组织项目的业务需求",我们创建了一些 Jira issue,以帮助我们分解需要构建的功能。在 "库存管理员解决方案"(Inventory Clerk Solution epic) 中,我们创建了一个标题如下的用户故事:

作为库存文员,我希望能够登录系统,以便访问库存系统。(As an inventory clerk, I want to be able to log in to the system so that I can access the inventory system.)

通过这个用户故事,我们可以推断出应用程序需要一个用户,而这个用户需要能够验证自己的身份,以便能够访问受限制的功能。

因此,通常情况下,作为软件开发人员,我们会继续开始构建解决方案代码—​编写代码,然后检查我们刚刚创建的控制器或网页的结果。我们不会这么做。

有了 BDD,我们将首先从失败的场景开始。听起来熟悉吗?是的—​从上一章开始,这就像我们在编写解决方案代码以通过失败测试之前,先编写失败的单元测试一样。

在开始编写 BDD 测试之前,我们需要使用一些 PHP 软件包来完成这项工作。我们将使用 Behat 测试框架来帮助我们构建和组织 BDD 测试。

什么是 Behat?

Behat 是一个 PHP 框架,用于在 PHP 中实现 BDD。它是一个帮助我们 PHP 开发人员编写行为驱动的测试和程序的框架。这将帮助我们更快地编写更好的行为驱动程序,这样我们就不必重新发明轮子来编写引导代码或骨架代码来编写这些行为驱动的测试。Behat 使用 Gherkin 来描述我们想要测试的实际功能。

Gherkin 是什么?

Gherkin 是一种用于定义业务场景和目标的语言。它采用简单的英文文本,因此公司中的任何人(甚至非技术人员)都能够理解所描述的业务场景。

什么是 Mink?

这就是它变得非常有趣的地方,至少对于像我这样的 PHP 开发人员来说是这样。 Mink 是一个 PHP 库,可以作为网络浏览器的模拟器。我们的网络应用程序开发人员开发 PHP 应用程序;我们的用户将通过网络浏览器使用我们的网络应用程序。因此,如果我们能将通过网络浏览器测试应用程序的过程自动化,将对我们大有裨益。我们可以使用一些程序来代替手动点击按钮或填写表格等操作。所以,想想看,一个机器人版本的你通过网络浏览器为你测试程序。

下一节,我们将安装 Behat。

安装 Behat 和 Mink

在开始编写第一个行为驱动测试程序之前,我们首先需要安装所需的所有库和依赖项。 让我们开始吧:

  1. codebase 目录下创建一个名为 behat 的新目录,以便我们可以拥有与 Symfony 应用程序不同的安装目录:

    image 2023 10 23 19 01 05 632
    Figure 1. Figure 6.1 – Behat root directory

    创建新目录后,我们可以继续通过 Composer 安装 Behat PHP 包。

  2. 使用终端在 behat 目录中运行以下命令:

    /var/www/html/behat# composer require --dev behat/behat
  3. 安装完成后,可以通过以下命令验证 Behat 是否安装成功:

    /var/www/html/behat# ./vendor/bin/behat -V

    完成后,您应该会看到刚刚安装的 Behat 版本:

    image 2023 10 23 19 10 47 739
    Figure 2. Figure 6.2 – Behat installed

现在,我们还需要安装 Mink,以便我们可以进行一些前端测试。

运行以下命令安装 Mink:

/var/www/html/behat# composer require --dev behat/minkextension -W
/var/www/html/symfony# composer require --dev behat/minkgoutte-driver

现在,我们需要让 Behat 创建一些框架文件来帮助我们开始。运行以下命令:

/var/www/html/behat# ./vendor/bin/behat --init

您现在应该看到一个名为 features 的新目录。这是我们放置业务功能场景的地方。

创建 Behat 功能

现在我们已经安装了 Behat 并对其进行了初始化,我们可以创建第一个示例功能文件。我们将使用 Gherkin 语言来定义该功能的故事。这实际上就像讲故事一样。

features 目录中,创建一个名为 home.feature 的新文件并添加以下内容:

/var/www/html/behat/features/home.feature
Feature: Home page
    In order to welcome visitors
    As a visitor
    I need to be able to see the Symfony logo

    Scenario: See the Symfony logo
        Given I have access to the home page URL
        When I visit the home page
        Then I should see the Symfony Logo

我们使用 Gherkin 语言创建了 featurescenario 文件。它们是描述性的并且非常容易理解。您不需要程序员就能理解它们的含义。因此,向业务分析师或测试工程师等同事展示它们不会成为问题;他们甚至可以帮助您微调或改进您的功能和场景。

接下来,我们将重点关注 Feature 关键字本身及其内容。

Feature 关键字

正如您在前面的代码片段中看到的,我们在 Feature 关键字下面编写了三个部分。下面列出了以下三个部分:

  • In order to <业务目标>

  • As a/an <参与者>

  • I need to be able to <之前定义的参与者应该能够做什么>

In order to 部分中,我们定义了企业希望在此功能中实现的目标。在我们的示例中,我们希望网站访问者在登陆我们的主页时感到受欢迎。

As a/an 部分中,我们定义谁正在执行该操作。在我们的示例中,这是正在访问主页的网站访问者。

最后,在 I need to be able to 部分中,我们定义 actor 应该能够做什么或实现什么,以便业务能够实现其最终目标。在我们的示例中,我们只希望演员或访客看到 Symfony 徽标和欢迎消息。

接下来,作为功能的一部分,我们需要使用 Scenario 关键字添加场景。

Scenario 关键字

在一项功能中,我们可以有一个或多个场景。在我们创建的 home.feature 文件中,您会注意到 Scenario 标签与其上面的 Feature 标签相比是缩进的。场景是用简单的英语写成的;它只是一系列事件的书面概述。在 Gherkin 中,我们也将场景分为三个部分:

  • Given:用于声明系统现有或当前的状态或值

  • When:用于定义在系统上执行的动词或操作

  • Then:执行 When 部分中声明的动词或操作后的预期结果

现在我们已经定义了示例功能和场景,让我们尝试运行 Behat 并看看我们会得到什么。

运行以下命令:

/var/www/html/behat# ./vendor/bin/behat

然后您应该看到以下结果:

image 2023 10 23 19 57 32 468
Figure 3. Figure 6.3 – Missing snippets

您会注意到 Behat 试图寻找一些代表我们之前声明的场景的 PHP 代码,但我们没有这样做。因此,这意味着我们还必须为 Behat 编写一些 PHP 代码,以便根据我们创建的实际 GivenWhenThen 定义来执行。

接下来,我们将编写支持我们刚刚创建的功能和场景所需的 PHP 代码。