🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## **简介** PHPUnit 作为一个 PHP 测试框架功能很强大,但是只能用于测试后端接口和功能,无法模拟浏览器端行为测试基于 JavaScript 的前端应用。 为此,Laravel为浏览器测试提供了一个官方扩展包——Laravel Dusk(该特性是在Laravel 5.4引入的),它基于[ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/home)(一个 Selenium WebDriver,支持桌面版和移动版 Chrome 浏览器)和[Facebook php-webdriver](https://github.com/facebook/php-webdriver)(Selenium WebDriver PHP 客户端)构建,我们可以通过它来模拟在浏览器中的任何操作,从而实现浏览器自动化测试的目的。 Laravel Dusk 为我们做好了底层封装,你不需要单独安装 Selenium,也不需要有之前使用过 Selenium 的经验,就可以通过 Dusk 提供的方法轻松上手浏览器自动化测试。下面我们就来简单介绍如何在 Laravel 项目中基于 Dusk 实现浏览器自动化测试。 > 注:Selenium 是一组工具集,用于实现测试自动化,关于 Selenium 的更多细节请参考[官方文档](https://www.seleniumhq.org/),或者阅读相应的[中文文档](https://www.kancloud.cn/wizardforcel/selenium-doc/102082)。 ## **安装配置** 首先,在 Laravel 项目根目录下通过 Composer 安装 Dusk 扩展包: ~~~ composer require --dev laravel/dusk ~~~ 我们只在本地开发环境或测试环境安装 Dusk,所以加上了`--dev`选项,如果在生产环境安装,存在安全风险,例如可以以任何用户的身份登录到应用,所以不建议在生产环境使用。 接下来,运行 Artisan 命令`dusk:install`执行初始化操作: ~~~ php artisan dusk:install ~~~ 该命令会在`tests`目录下创建一个`Browser`目录并包含一个测试用例示例: ![](https://img.kancloud.cn/a1/b2/a1b2452f6ea7f7fa03f98467a118226c_1712x824.jpg) 从根源上看,浏览器测试用例也是继承自`PHPUnit\Framework\TestCase`,所以可以在用例中使用前面提到的所有 PHPUnit 及 Laravel 框架提供的断言方法。 你可能已经注意到生成的子目录中还包含了一个`screenshots`目录,当测试失败时,Dusk 会将屏幕截屏并将图片保存到该目录,这在调试时很有帮助。 接下来,需要更新`.env`文件中的`APP_URL`配置项,这里配置为项目的虚拟域名即可,比如`http://laravel58.test`,该域名需要和 Web 服务器中的配置保持一致,以便可以通过浏览器访问。 > 注:除此之外,你还可以让 Dusk 选择使用自己独立的环境配置文件,例如`.env.dusk.local`,如果是测试环境,则对应的配置文件是`.env.dusk.testing`。 ## **运行测试** 做好以上初始化工作后,就可以在项目根目录下通过如下 Artisan 命令基于 Dusk 运行浏览器测试了: ~~~ php artisan dusk ~~~ 该命令会运行`tests\Browser\ExampleTest.php`文件中的`ExampleTest`: ~~~ class ExampleTest extends DuskTestCase { /** * A basic browser test example. * * @return void */ public function testBasicExample() { $this->browse(function (Browser $browser) { $browser->visit('/') ->assertSee('Laravel'); }); } } ~~~ 其中,我们向`browse`方法传入了一个包含`Browser`实例的回调,在该回调中,我们可以基于`Browser`实例提供的方法模拟浏览器的各种操作,然后通过断言方法对结果进行测试。比如这里通过`visit`方法模拟在浏览器中访问`http://laravel58.test/`URL,然后通过`assertSee`方法断言结果页面是否包含`Laravel`字符串。 如果测试失败,就会在`tests/Browser/screenshots`目录下生成一张测试失败时的页面截图。 看完这个最基本的测试用例,下面我们来看一些稍微复杂一点的例子。 ## **表单和认证** 通过 Dusk 还可以与表单进行交互,下面我们基于 Laravel[认证脚手架代码](https://xueyuanjun.com/post/19484.html#toc_2)模拟表单交互来测试用户认证功能。 完整认证脚手架代码生成和数据库迁移后,我们通过如下 Artisan 命令创建一个新的浏览器测试用例`RegisterTest`: ~~~ php artisan dusk:make RegisterTest ~~~ 该命令会在`tests/Browser`目录下生成`RegisterTest.php`文件,我们修改`testExample`方法如下: ~~~ /** * A Dusk register test example. * * @return void */ public function testExample() { $this->browse(function (Browser $browser) { $browser->visit('/') // 访问首页 ->clickLink('Register') // 点击注册按钮 ->assertSee('Register') // 断言注册页面包含Register文本 // 通过下面这些值填充注册表单 ->value('#name', 'test_01') ->value('#email', 'test_01@laravel58.test') ->value('#password', 'test123456') ->value('#password-confirm', 'test123456') ->click('button[type="submit"]') // 点击注册按钮 ->assertPathIs('/home') // 注册成功后跳转到 /home 页面 ->assertSee("You are logged in!"); // 登录成功后提示文本 }); } ~~~ 在这段测试用例中,我们首先访问应用首页,然后通过`clickLink`方法模拟点击注册链接,进入注册页面后,先断言页面是否包含「Register」文本,然后通过`value`方法填充表单,在该方法中,第一个参数是 CSS 选择器,第二个是对应输入框的值,表单填充完毕后,通过`click`方法模拟点击注册按钮提交表单,提交表单注册成功后,断言页面是否跳转到`/home`路由,并断言登录成功提示文本是否出现,至此,我们就编写好了注册流程的自动化测试。 显然,相比于通过 Laravel 功能测试编写的测试用例,浏览器测试功能更加强大,更具有整体性,因为功能测试只能模拟测试指定的后端路由,而浏览器测试可以模拟完整的用户操作流程,能够在一个用例中测试一个完整的事务。 编写好浏览器测试代码后,再次运行测试用例: ~~~ php artisan dusk ~~~ 测试通过,此时查看数据库,会发现`users`表中新增了一个名为`test_01`的测试用户。 你可以模仿注册流程测试下用户登录流程,除此之外,Dusk 还支持很多与其他页面元素的交互以及额外封装的断言方法,具体可以参考[官方文档](https://xueyuanjun.com/post/19543.html)。