使用 Mink 的浏览器进行测试
到目前为止,我们已经能够为脚本编写验收测试,但你们中的大多数人阅读本书的目的是为了编写漂亮、闪亮的网络应用程序。那么如何利用验收测试呢?是时候介绍本章的第二个 PHP 工具了: Mink。
Mink 实际上是 Behat 的一个扩展,它增加了与网络浏览器测试相关的几个步骤的实现。例如,如果将 Mink 添加到应用程序中,就能添加 Mink 启动浏览器并按要求点击或键入的场景,从而节省大量手动测试的时间和精力。不过,首先让我们来看看 Mink 是如何实现这一点的。
web驱动的类型
Mink 使用网络驱动程序,也就是拥有 API 的库,可以让你与浏览器进行交互。您可以发送命令,例如转到此页面、点击此链接、在此输入框中填写此文本等,网络驱动程序会将这些命令转化为浏览器的正确指令。网络驱动程序有好几种,每种都采用不同的方法。因此,根据网络驱动程序的不同,你可以获得某些功能,也可以获得其他功能。
根据工作方式的不同,网络驱动程序可分为两类:
-
无头浏览器:这些驱动程序并不真正启动浏览器,而只是尝试模拟浏览器。它们实际上是请求网页并渲染 HTML 和 JavaScript 代码,因此它们知道网页的外观,但不显示网页。它们有一个巨大的优点:易于安装和管理,而且由于无需构建图形表示法,因此速度极快。缺点是它们在 CSS 和某些 JavaScript 功能(尤其是 AJAX)方面有很大限制。
-
网络驱动程序可以像用户一样启动真正的浏览器: 这些网络驱动程序几乎无所不能,功能比无头浏览器强大得多。问题是,它们的安装可能有点麻烦,而且速度非常非常慢—就像一个真正的用户尝试通过各种场景一样慢。
那么,您应该选择哪一种呢?一如既往,这取决于你的应用是什么。如果您的应用程序并不大量使用 CSS 和 JavaScript,而且对您的业务也不重要,那么您可以使用无头浏览器。相反,如果应用程序是您业务的基石,而且您需要绝对确定所有用户界面功能都能按预期运行,那么您可能需要使用可启动浏览器的网络驱动程序。
使用 Goutte 安装 Mink
在本章中,我们将使用由开发 Symfony 的同一批人编写的无头网络驱动程序 Goutte,在 GitHub 的版本库页面上添加一些验收测试。项目所需的组件包括 Behat、Mink 和 Goutte 驱动程序。使用 Composer 通过以下命令添加它们:
$ composer require behat/behat
$ composer require behat/mink-extension
$ composer require behat/mink-goutte-driver
现在,执行以下行来要求 Behat 创建基本目录结构:
$ ./vendor/bin/behat –init
我们要对 FeatureContext 类做的唯一改动就是它从哪里扩展而来。这一次,我们将使用 MinkContext 来获取与网络测试相关的所有步骤定义。FeatureContext 类的外观应与此相似:
<?php
use Behat\MinkExtension\Context\MinkContext;
require __DIR__ . '/../../vendor/autoload.php';
class FeatureContext extends MinkContext
{
}
Mink 还需要一些配置,以便让 Behat 知道我们要使用哪个网络驱动程序或测试的基本 URL。在 behat.yml 中添加以下信息:
default:
extensions:
Behat\MinkExtension:
base_url: "https://github.com"
sessions:
default_session:
goutte: ~
有了这项配置,我们就能让 Behat 知道我们使用的是 Mink 扩展,Mink 将在所有会话中使用 Goutte(如果有必要,可以使用不同的网络驱动程序定义不同的会话),并且这些测试的基础 URL 是 GitHub 的 URL。Behat 已被指示在我们执行测试的同一目录下查找 behat.yml 文件,因此我们无需再做其他操作。
与浏览器交互
现在,让我们来看看其中的奥妙。如果你知道使用步骤,用 Mink 写验收测试就会像玩游戏一样简单。首先,在 feature/search 中添加以下功能:
Feature: Search
In order to find repositories
As a website user
I need to be able to search repositories by name
Background:
Given I am on "/picahielos"
And I follow "Repositories"
Scenario: Searching existing repository
When I fill in "zap" for "q"
And I press "Search"
Then I should see "picahielos/zap"
Scenario: Searching non-existing repository
When I fill in "yolo" for "q"
And I press "Search"
Then I should not see "picahielos/yolo"
首先要注意的是,我们有一个 Background 部分。该部分假设用户访问了 https://github.com/picahielos 页面并点击了 Repositories 链接。使用 I follow with some string 相当于尝试查找包含此字符串的链接并点击它。
第一种情况使用了 When I fill <field> with <value> 步骤,它基本上会尝试在页面上找到输入字段(您可以指定 ID 或名称),并为您键入值。在这种情况下,q 字段是搜索栏,我们键入了 zap。然后,类似于点击链接时,I press <button> 行将尝试按名称、ID 或值查找按钮,并单击它。最后,Then I should see followed by a string 将断言可以在页面上找到给定的字符串。简而言之,测试启动了一个浏览器,转到指定的 URL,点击 Repositories 链接,搜索 zap 存储库,并断言可以找到它。以类似的方式,第二种情况试图查找一个不存在的存储库。
如果你运行这些测试,它们应该会通过,但你不会看到任何浏览器。记住,Goutte 是一个无头浏览器 Web 驱动程序。但是,检查这些测试的执行速度有多快;在我的笔记本电脑上,它只花了不到3秒!你能想象有人手动执行这两个测试的时间比这还短吗?
最后一点:在办公桌旁放一张预定义 Mink 步骤的备忘单是最方便的事情之一;您可以在 http://blog.lepine.pro/images/2012-03-behat-cheat-sheet-en.pdf 上找到一张。如您所见,我们没有写一行代码,但我们仍然有两个测试,以确保网站按预期运行。此外,如果您需要添加一个更花哨的步骤,请不要担心;您仍然可以像之前在Behat中那样实现步骤定义,同时利用 Mink 提供的 Web 驱动程序接口。我们建议您阅读官方文档,以查看您可以使用 Mink 完成的完整列表。
总结
在最后一章中,你学习了业务与应用程序的协调是多么重要。为此,你了解了什么是 BDD 以及如何使用 Behat 和 Mink 在 PHP Web 应用程序中实现它。这也使你能够使用 Web 驱动程序测试 UI,这是单元测试和 PHPUnit 无法做到的。现在,你可以确保你的应用程序不仅没有缺陷而且安全,而且它还能满足业务需求。
恭喜你读完了这本书!你开始时是一名没有经验的开发人员,但现在你可以用 PHP 编写简单和复杂的网站和 REST API,并且对良好的测试实践有广泛的知识。你甚至使用过几个著名的 PHP 框架,所以你已经准备好与他们一起开始一个新的项目,或者加入一个使用其中一个框架的团队。
现在,你可能会想:接下来我该做什么?你已经知道理论了——好吧,是其中一部分——所以我们建议你多练习。你可以通过几种方式来练习:创建自己的应用程序,加入一个开源项目团队,或者为一家公司工作。试着跟上语言或工具和框架的新版本,不时地发现一个新的框架,并且永远不要停止阅读。扩展你的技能总是一个好主意!
如果你不知道接下来读什么,这里有一些提示。我们没有过多地研究前端部分,所以你可能对 CSS 和特别是 JavaScript 感兴趣。JavaScript 在最近几年已经成为主角,所以不要错过它。如果你对后端以及如何正确管理应用程序很感兴趣,可以尝试发现新技术,例如类似于 Jenkins 的持续集成工具。最后,如果你更喜欢关注理论和 “科学” 方面,你可以阅读如何使用 Code Complete、Steve McConnell 编写高质量代码,或者如何利用 Erich Gamma、John Vlissides、Ralph Johnson 和 Richard Helm 等四人编写的《设计模式:可复用面向对象软件要素》中提到的设计模式。
在开发过程中始终享受乐趣。