浏览器测试 | 测试系列 | Laravel 6 中文文档


本站和网页 https://laravelacademy.org/post/19983.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

浏览器测试 | 测试系列 | Laravel 6 中文文档
Laravel 学院
文档
Laravel 8.x 中文文档
Laravel 7.x 中文文档
Laravel 6.x 中文文档
Laravel 5.8 中文文档
Laravel 5.7 中文文档
Laravel 5.6 中文文档
Laravel 5.5 中文文档
Laravel 5.4 中文文档
Laravel 5.3 中文文档
Laravel 5.2 中文文档
Laravel 5.1 中文文档
Lumen 中文文档
全栈教程
PHP 全栈工程师指南
PHP 入门到实战
Laravel 入门到精通
Vue.js 入门到实战
玩转 PhpStorm 教程
Laravel 博客入门项目
Laravel 微信小程序项目
Laravel 前后端分离项目
Swoole 入门到实战
Eloquent 性能优化实战
Redis 高性能实战系列
Laravel 新版本特性
PHP 新特性与最佳实践
Golang
Go 入门教程
Go Web 编程
Gin 使用教程
微服务开发
内功修炼
数据结构与算法
网络协议
微服务从入门到实践
高性能 MySQL 实战
高性能 Redis 实战
Laravel 消息队列实战
Laravel 从学徒到工匠
PHP 设计模式系列
名企面试指南
资源库
Laravel 资源大全
Laravel 开源项目
Laravel 扩展包
Laravel 资源下载
更多
博客 & 新闻
问答 & 讨论
Leetcode 题解
学院君读书笔记系列
关于 Laravel 学院
Laravel 互助学习群
Golang 互助学习群
更多
Laravel 中文文档
Laravel 全栈教程
Laravel 学习路径
Go 入门教程
程序员内功修炼
博客
问答
搜索
注册
登录
Info
Content
章节导航
Laravel 6 中文文档
目录索引
序言
3篇文章
新版特性
升级指南
贡献指南
快速入门
5篇文章
安装配置
目录结构
重量级开发环境:Homestead
轻量级开发环境:Valet
部署应用到服务器
核心架构
5篇文章
一次 Laravel 请求的生命周期
服务容器
服务提供者
门面
契约
基础组件
12篇文章
路由
中间件
CSRF 保护
控制器
HTTP 请求
HTTP 响应
视图
URL 生成
Session
表单验证
异常处理
日志
前端开发
4篇文章
Blade 模板引擎
本地化
快速入门:JavaScript & CSS 脚手架
使用进阶:通过 Laravel Mix 编译前端资源
安全系列
7篇文章
登录认证
API 认证
授权
邮箱验证
加密
哈希
重置密码
进阶系列
12篇文章
Artisan 控制台
广播
缓存
集合
事件
文件存储
辅助函数
邮件
通知
扩展包开发
队列
任务调度
数据库操作
6篇文章
快速入门
查询构建器
分页
迁移
数据填充
Redis
Eloquent模型
6篇文章
快速入门
关联关系
集合
API 资源类
访问器和修改器
序列化
测试系列
6篇文章
快速入门
HTTP 测试
浏览器测试
控制台测试
数据库测试
模拟
官方扩展包
7篇文章
订阅支付解决方案:Laravel Cashier
远程操作解决方案:Laravel Envoy
队列系统解决方案:Laravel Horizon
API 认证解决方案:Laravel Passport
全文搜索解决方案:Laravel Scout
第三方登录解决方案:Laravel Socialite
本地开发调试解决方案:Laravel Telescope
图书
Laravel 6 中文文档
测试系列
浏览器测试
浏览器测试
由 学院君 创建于3年前, 最后更新于 3年前
版本号 #1
4051 views
0 likes
0 collects
简介
Laravel Dusk 提供了优雅的、易于使用的浏览器自动测试 API。默认情况下,Dusk 不强制你在机器上安装 JDK 或 Selenium,取而代之地,Dusk 基于独立安装的 ChromeDriver。不过,你可以使用任意其他兼容 Selenium 的驱动。
注:Selenium 是一套 Web 应用自动化测试系统,运行 Selenium 测试就像你在浏览器中操作一样;WebDriver 提供更精简的编程接口,以解决 Selenium-RC API 中的一些限制,WebDriver 的目标是提供一套精心设计的、面向对象的 API 来更好地支持现代高级 Web 应用的测试工作。Selenium 2.0 开始就已经集成了 WebDriver API,不过你仍然可以独立使用 WebDriver API,ChromeDriver 由 Chronium 团队维护,是为基于 Chronium(含 Chrome)浏览器提供的、实现了 WebDriver wire 协议的独立服务器,安装完 Dusk 扩展包会自带 ChromeDriver,无需手动安装。
安装
开始之前,需要添加 Composer 依赖 laravel/dusk 到项目:
composer require --dev laravel/dusk
注:如果你是手动注册 Dusk 服务提供者,永远不要将其注册到生产环境,这会导致所有用户都可以登录到应用。
接下来,运行 Artisan 命令 dusk:install:
php artisan dusk:install
运行完该命令后,会在 tests 目录下新建一个 Browser 目录并包含一个测试示例。接下来,在 .env 文件中设置环境变量 APP_URL,该变量值需要和你在浏览器中用于访问应用的 URL 相匹配。
要运行测试,使用 Artisan 命令 dusk。dusk 命令接收任意 phpunit 支持的参数:
php artisan dusk
如果你上一次运行 dusk 命令测试失败,可以通过使用 dusk:fails 命令重新运行首次失败的测试来节省时间:
php artisan dusk:fails
注:Dusk 要求 chromedriver 二进制文件可执行,如果运行 Dusk 时有问题,需要运行 chmod -R 0755 vendor/laravel/dusk/bin 来确保该二进制文件有可执行权限。
管理 ChromeDriver 安装
如果你想要安装与 Laravel Dusk 内置版本不同的其他 ChromeDriver,可以使用 dusk:chrome-driver 命令安装:
# 安装与当前操作系统适配的最新版本 ChromeDriver
php artisan dusk:chrome-driver
# 安装与当前操作系统适配的指定版本 ChromeDriver
php artisan dusk:chrome-driver 74
# 安装所有支持操作系统的 ChromeDriver
php artisan dusk:chrome-driver --all
注:Dusk 要求 chromedriver 二进制文件具有可执行权限。如果你在运行 Dusk 时遇到问题,可以通过如下命令确保这个二进制文件可执行:chmod -R 0755 vendor/laravel/dusk/bin/。
使用其它浏览器
默认情况下,Dusk 使用 Google Chrome 和独立安装的 ChromeDriver 来运行浏览器测试(Dusk 扩展包自带),不过,你也可以启动自己的 Selenium 服务器并在浏览器中进行测试。
开始之前,打开 tests/DuskTestCase.php 文件,该文件是应用的 Dusk 测试用例基类。 在该文件中,你可以移除对 startChromeDriver 方法的调用,这样,就可以阻止 Dusk 自动启动 ChromeDriver:
/**
* Prepare for Dusk test execution.
* @beforeClass
* @return void
*/
public static function prepare()
// static::startChromeDriver();
接下来,可以编辑 driver 方法连接到你所选择的 URL 和接口,此外,你可以编辑需要传递给 WebDriver 的“期望功能”:
/**
* 创建 RemoteWebDriver 实例.
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
*/
protected function driver()
return RemoteWebDriver::create(
'http://localhost:4444/wd/hub', DesiredCapabilities::phantomjs()
);
快速入门
生成测试
要生成一个 Dusk 测试,使用 Artisan 命令 dusk:make,生成的测试位于 tests/Browser 目录:
php artisan dusk:make LoginTest
运行测试
要运行浏览器测试,使用 Artisan 命令 dusk:
php artisan dusk
如果你上一次运行 dusk 命令测试失败,可以通过使用 dusk:fails 命令重新运行首次失败的测试来节省时间:
php artisan dusk:fails
dusk 命令接收任意 PHPUnit 支持的参数,所以你可以为给定 group 运行测试:
php artisan dusk --group=foo
手动启动 ChromeDriver
默认情况下,Dusk 会自动尝试启动 ChromeDriver,如果在你的系统上不生效,你可以在运行 dusk 命令前手动启动 ChromeDriver。如果你选择了手动启动 ChromeDriver,则需要注释掉 tests/DuskTestCase.php 文件中的如下这行代码:
/**
* Prepare for Dusk test execution.
* @beforeClass
* @return void
*/
public static function prepare()
// static::startChromeDriver();
此外,如果你不是在 9515 端口上启动 ChromeDriver,需要在同一个类中编辑 driver 方法:
/**
* Create the RemoteWebDriver instance.
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
*/
protected function driver()
return RemoteWebDriver::create(
'http://localhost:9515', DesiredCapabilities::chrome()
);
环境处理
要想在运行测试时强制 Dusk 使用自己的环境文件,可以在项目根目录下创建一个 .env.dusk.{environment} 文件,例如,如果你是在 local 环境中启动 dusk 命令,需要创建 .env.dusk.local 文件。
运行测试的时候,Dusk 会备份 .env 文件,并将 Dusk 环境文件重命名为 .env。一旦测试完成,.env文件会被恢复。
创建浏览器
作为入门,我们编写一个测试来验证可以登录到应用,生成测试之后,编辑测试类将其导航到登录页面,输入认证信息,点击登录按钮。要创建浏览器实例,调用 browse 方法:
<?php
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Chrome;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class LoginTest extends DuskTestCase
use DatabaseMigrations;
/**
* A basic browser test example.
* @return void
*/
public function testBasicExample()
$user = factory(User::class)->create([
'email' => 'taylor@laravel.com',
]);
$this->browse(function ($browser) use ($user) {
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'secret')
->press('Login')
->assertPathIs('/home');
});
正如你在上面示例中所看到的,browse 方法接收一个回调,浏览器实例会通过 Dusk 自动传递给这个回调并且作为主要对象和应用进行交互并生成断言。
创建多个浏览器
有时候你需要多个浏览器以便完成测试,例如,在测试通过 Web 套接字进行交互的聊天室页面时就需要多个浏览器。要创建多个浏览器,只需在调用 browse 方法时在回调标识中指明需要的浏览器即可:
$this->browse(function ($first, $second) {
$first->loginAs(User::find(1))
->visit('/home')
->waitForText('Message');
$second->loginAs(User::find(2))
->visit('/home')
->waitForText('Message')
->type('message', '学院君你好')
->press('Send');
$first->waitForText('学院君你好')
->assertSee('学院君');
});
调整浏览器窗口尺寸
你可以使用 resize 方法来调整浏览器窗口尺寸:
$browser->resize(1920, 1080);
maximize 方法可用于最大化浏览器窗口:
$browser->maximize();
浏览器宏
如果你想要定义一个自定义的浏览器方法以便在测试中复用,可以使用 Browser 类提供的 macro 方法。通常,需要在服务提供者的 boot 方法中调用该方法:
<?php
namespace App\Providers;
use Laravel\Dusk\Browser;
use Illuminate\Support\ServiceProvider;
class DuskServiceProvider extends ServiceProvider
/**
* Register the Dusk's browser macros.
* @return void
*/
public function boot()
Browser::macro('scrollToElement', function ($element = null) {
$this->script("$('html, body').animate({ scrollTop: $('$element').offset().top }, 0);");
return $this;
});
macro 方法接收方法名作为第一个参数,以及一个闭包作为第二个参数。该闭包会在 Browser 实现上调用该宏方法时执行:
$this->browse(function ($browser) use ($user) {
$browser->visit('/pay')
->scrollToElement('#credit-card-details')
->assertSee('Enter Credit Card Details');
});
认证
我们经常会测试需要认证的页面,可以使用 Dusk 的 loginAs 方法用于避免在每个测试中与登录页面进行交互,loginAs 方法接收用户 ID 或用户模型实例:
$this->browse(function ($first, $second) {
$first->loginAs(User::find(1))
->visit('/home');
});
注:使用 loginAs 方法后,用户会话在某个文件中被所有测试维护。
数据库迁移
测试需要迁移时,例如上面的认证示例,不要使用 RefreshDatabase trait,RefreshDatabase trait 会影响不能跨请求应用的数据库事务。取而代之的,我们使用 DatabaseMigrations trait:
<?php
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Chrome;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends DuskTestCase
use DatabaseMigrations;
与页面元素交互
Dusk 选择器
编写 Dusk 测试最困难的部分之一就是为元素交互选择好的 CSS 选择器,随着时间的推移,前端的改变可能导致 CSS 选择器像下面这样中断测试:
// HTML...
<button>Login</button>
// Test...
$browser->click('.login-page .container div > button');
Dusk 选择器允许你专注于编写高效的测试而不是记住 CSS 选择器。要定义一个选择器,添加 dusk 属性到 HTML 元素,然后,通过在选择器前添加 @ 前缀在 Dusk 测试中操作元素:
// HTML...
<button dusk="login-button">Login</button>
// Test...
$browser->click('@login-button');
点击链接
要点击链接,可以使用浏览器实例上的 clickLink 方法,clickLink 方法将会点击包含给定文本的链接:
$browser->clickLink($linkText);
注:该方法通过 jQuery 进行交互,如果 jQuery 在页面上无效,Dusk 会自动将其注入到页面,以便在测试期间生效。
文本、值 & 属性
获取 & 设置值
Dusk 提供了多个方法用于和页面元素的当前显示文本、值和属性进行交互,例如,要获取匹配给定选择器的元素值,使用 value 方法:
// 获取值...
$value = $browser->value('selector');
// 设置值...
$browser->value('selector', 'value');
获取文本
text 方法可用于获取匹配给定选择器的元素显示文本:
$text = $browser->text('selector');
获取属性
最后,attribute 方法可用于获取匹配给定选择器的元素属性:
$attribute = $browser->attribute('selector', 'value');
使用表单
输入值
Dusk 提供了多个方法与表单和输入元素进行交互,首先,让我们看一个输入文本到一个输入字段的例子:
$browser->type('email', 'xueyuanjun@laravelacademy.org');
注意,虽然 type 方法在需要的时候可以接收,但是我们也不是必须要传递 CSS 选择器到该方法。如果没有提供 CSS 选择器,Dusk 会搜索包含给定 name 属性的输入字段,最后,Dusk 会尝试查找包含给定 name 属性的 textarea。
要追加文本到某个字段而不清除其值,可以使用 append 方法:
$browser->type('tags', 'foo')
->append('tags', ', bar, baz');
你可以使用 clear 方法“清除”输入的值:
$browser->clear('email');
下拉框
要在下拉选择框中选择值,可以使用 select 方法。和 type 方法一样,select 方法不需要完整的 CSS 选择器,当传递值到 select 方法时,需要传递底层 option 值而不是显示文本:
$browser->select('size', 'Large');
你可以通过省略第二个参数来选择一个随机的 option:
$browser->select('size');
复选框
要“选择”复选字段,可以使用 check 方法,和其它输入相关方法一样,不需要传入完整的 CSS 选择器,如果找不到精准匹配的选择器,Dusk 会通过一个相匹配 name 属性来搜索复选框:
$browser->check('terms');
$browser->uncheck('terms');
单选按钮
要“选择”一个单选按钮选项,可以使用 radio 方法,和其它输入相关方法一样,不需要完整的 CSS 选择器,如果找不到精准匹配的选择器,Dusk 会搜索匹配 name 和 value 属性的单选框:
$browser->radio('version', 'php7');
上传文件
attach 方法可用于上传文件到 file 输入元素,和其它输入相关方法一样,也不需要完整的 CSS 选择器,如果精准匹配的选择器找不到,Dusk 会通过 name 属性搜索匹配的文件输入:
$browser->attach('photo', __DIR__.'/photos/me.png');
注:使用 attach 函数要求系统安装并启用了了 PHP Zip 扩展。
使用键盘
keys 方法允许你提供比 type 方法更多的复杂输入序列到给定元素。例如,你可以存放编辑键及对应输入值,在本例中,shift键会被存放而taylor被输入到与给定选择器匹配的元素中。输入taylor后,otwell会以不带任何编辑键的形式被输入:
$browser->keys('selector', ['{shift}', 'taylor'], 'otwell');
你甚至还可以发送“热键”到包含应用的主CSS选择器上:
$browser->keys('.app', ['{command}', 'j']);
注:所有编辑键都被包裹在 {} 中,并匹配定义在 Facebook\WebDriver\WebDriverKeys 类中的常量,这些常量可以在GitHub上找到。
使用鼠标
点击元素
click 方法可用于点击与给定选择器匹配的元素:
$browser->click('.selector');
鼠标悬停
mouseover 方法可以在你将鼠标悬停在与给定选择器匹配的元素上时使用:
$browser->mouseover('.selector');
拖拽
drag 方法可用于拖放与给定选择器匹配的元素到另一个元素:
$browser->drag('.from-selector', '.to-selector');
或者,你可以在单个方向上拖放元素:
$browser->dragLeft('.selector', 10);
$browser->dragRight('.selector', 10);
$browser->dragUp('.selector', 10);
$browser->dragDown('.selector', 10);
JavaScript 对话框
Dusk 提供多个方法与 JavaScript 对话框交互:
// Wait for a dialog to appear:
$browser->waitForDialog($seconds = null);
// Assert that a dialog has been displayed and that its message matches the given value:
$browser->assertDialogOpened('value');
// Type the given value in an open JavaScript prompt dialog:
$browser->typeInDialog('Hello World');
要关闭一个打开的 JavaScript 对话框,可以点击确定按钮:
$browser->acceptDialog();
也可以点击取消按钮:
$browser->dismissDialog();
选择器作用域
有时候你可能只想要在某个给定选择器上执行一系列操作,例如,你可能想要在某个表格中断言文本是否存在然后在同一个表格中点击按钮。你可以使用 with 方法来完成这一功能,传递给 with 方法的回调中所有被执行的操作都被限制在给定的选择器中:
$browser->with('.table', function ($table) {
$table->assertSee('Hello World')
->clickLink('Delete');
});
等待元素
当测试到广泛使用 JavaScript 的应用时,经常需要等待特定元素或数据加载完成之后才能进行测试。Dusk 让这种测试变得简单,通过使用多种方法,你可以在页面上等待元素变得可访问,甚至直到给定 JavaScript 表达式值为 true。
等待
如果你需要暂停测试指定毫秒数,可以使用 pause 方法:
$browser->pause(1000);
等待选择器
waitFor 方法可用于暂停测试执行直到匹配给定 CSS 选择器的元素在页面上显示。默认情况下,这将会在抛出异常前暂停测试最多5秒,如果需要的话,你可以传递自定义超时时间作为该方法的第二个参数:
// 最多等待选择器5s...
$browser->waitFor('.selector');
// 最多等待选择器1s...
$browser->waitFor('.selector', 1);
还可以等到给定选择器在页面消失:
$browser->waitUntilMissing('.selector');
$browser->waitUntilMissing('.selector', 1);
选择器作用域(有效的话)
某些情况下,你可能想要等待给定选择器然后和匹配给定选择器的元素进行交互。例如,你可能想要等待直到模态窗口有效然后在该窗口中按下“OK”按钮。whenAvailable 方法可以用于此种案例。给定回调中的所有元素操作执行都会限制在特定选择器中:
$browser->whenAvailable('.modal', function ($modal) {
$modal->assertSee('Hello World')
->press('OK');
});
等待文本
waitForText 方法可用于等到给定文本在页面上显示:
// 最多等待文本5s...
$browser->waitForText('Hello World');
// 最多等待文本1s...
$browser->waitForText('Hello World', 1);
等待链接
waitForLink 方法可用于等到给定链接文本在页面上显示:
// 最多等待链接5s...
$browser->waitForLink('Create');
// 最多等待链接1s...
$browser->waitForLink('Create', 1);
等待页面加载
当进行页面断言如 $browser->assertPathIs('/home') 时,如果 window.location.pathname 被异步更新则断言会失败。你可以使用 waitForLocation 方法等待 location 成为给定值:
$browser->waitForLocation('/secret');
还可以等待命名路由的 location:
$browser->waitForRoute($routeName, $parameters);
等待页面重载
如果你需要在页面重载后断言,可以使用 waitForReload 方法:
$browser->click('.some-action')
->waitForReload()
->assertSee('something');
等待 JavaScript 表达式
有时候你可能想要暂定测试直到 JavaScript 表达式值为 true。你可以简单通过 waitUntil 方法完成这一功能。当暂停表达式时,不需要包含 return 关键词或者结束分号:
// Wait a maximum of five seconds for the expression to be true...
$browser->waitUntil('App.dataLoaded');
$browser->waitUntil('App.data.servers.length > 0');
// Wait a maximum of one second for the expression to be true...
$browser->waitUntil('App.data.servers.length > 0', 1);
等待 Vue 表达式
下面的方法可用于等待直到给定 Vue 组件属性包含指定值:
// Wait until the component attribute contains the given value...
$browser->waitUntilVue('user.name', 'Taylor', '@user');
// Wait until the component attribute doesn't contain the given value...
$browser->waitUntilVueIsNot('user.name', null, '@user');
带回调的等待
Dusk 里面的很多「wait」方法依赖于底层的 waitUsing 方法。你可以直接使用这个方法来等待给定回调返回 true,waitUsing 方法接收等待的最大秒数、闭包执行的时间间隔、闭包以及可选的失败信息:
$browser->waitUsing(10, 1, function () use ($something) {
return $something->isReady();
}, "Something wasn't ready in time.");
Vue 断言
Dusk 甚至允许你对 Vue 组件数据的状态进行断言,例如,假设你的应用包含了如下 Vue 组件:
// HTML...
<profile dusk="profile-component"></profile>
// Component Definition...
Vue.component('profile', {
template: '<div>{{ user.name }}</div>',
data: function () {
return {
user: {
name: '学院君'
};
});
你可以像这样断言 Vue 组件状态:
/**
* A basic Vue test example.
* @return void
*/
public function testVue()
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertVue('user.name', '学院君', '@profile-component');
});
有效的断言
Dusk 提供了多种断言用于应用测试,所有有效的断言罗列如下:
断言
描述
$browser->assertTitle($title)
断言页面标题匹配给定文本
$browser->assertTitleContains($title)
断言页面标题包含给定文本
$browser->assertUrlIs($url)
断言当前URL(不含查询字符串)匹配给定字符串
$browser->assertSchemeIs($scheme)
断言当前 URL scheme 是否匹配给定 scheme
$browser->assertSchemeIsNot($scheme)
断言当前 URL scheme 是否不匹配给定 scheme
$browser->assertHostIs($host)
断言当前 URL host 是否匹配给定 host
$browser->assertHostIsNot($host)
断言当前 URL host 是否不匹配给定 host
$browser->assertPortIs($port)
断言当前 URL port 是否匹配给定 port
$browser->assertPortIsNot($port)
断言当前 URL port 是否不匹配给定 port
$browser->assertPathBeginsWith($path)
断言当前路径以给定路径开头
$browser->assertPathIs('/home')
断言当前路径匹配给定路径
$browser->assertPathIsNot('/home')
断言当前路径不匹配给定路径
$browser->assertRouteIs($name, $parameters)
断言当前URL匹配给定命名路由URL
$browser->assertQueryStringHas($name, $value)
断言给定查询字符串参数存在并包含给定值
$browser->assertQueryStringMissing($name)
断言给定查询字符串参数缺失
$browser->assertFragmentIs($fragment)
断言当前片段是否与给定片段匹配
$browser->assertFragmentBeginsWith($fragment)
断言当前片段是否以给定片段开头
$browser->assertFragmentIsNot($fragment)
断言当前片段是否与给定片段不匹配
$browser->assertHasCookie($name)
断言给定Cookie存在
$browser->assertCookieMissing($name)
断言给定Cookie不存在
$browser->assertCookieValue($name, $value)
断言Cookie包含给定值
$browser->assertPlainCookieValue($name, $value)
断言未加密Cookie包含给定值
$browser->assertSee($text)
断言给定文本在页面存在
$browser->assertDontSee($text)
断言给定文本在页面不存在
$browser->assertSeeIn($selector, $text)
断言给定文本在指定选择器中存在
$browser->assertDontSeeIn($selector, $text)
断言给定文本在指定选择器中不存在
$browser->assertSourceHas($code)
断言给定源码在页面中存在
$browser->assertSourceMissing($code)
断言给定源码在页面中不存在
$browser->assertSeeLink($linkText)
断言给定链接在页面中存在
$browser->assertDontSeeLink($linkText)
断言给定链接在页面中不存在
$browser->assertInputValue($field, $value)
断言给定输入字段包含给定值
$browser->assertInputValueIsNot($field, $value)
断言给定输入字段不包含给定值
$browser->assertChecked($field)
断言给定复选框被选中
$browser->assertNotChecked($field)
断言给定复选框未被选中
$browser->assertRadioSelected($field, $value)
断言给定单选框被选中
$browser->assertRadioNotSelected($field, $value)
断言给定单选框未被选中
$browser->assertSelected($field, $value)
断言给定下拉框包含给定选择值
$browser->assertNotSelected($field, $value)
断言给定下拉框不包含给定选择值
$browser->assertSelectHasOptions($field, $values)
断言给定数值数组可以被选择
$browser->assertSelectMissingOptions($field, $values)
断言给定数值数组不能被选择
$browser->assertSelectHasOption($field, $value)
断言给定数值可以被选择
$browser->assertValue($selector, $value)
断言匹配给定选择器的元素包含给定值
$browser->assertVisible($selector)
断言匹配给定选择器的元素可见
$browser->assertPresent($selector)
断言匹配给定选择器的元素是否存在
$browser->assertMissing($selector)
断言匹配给定选择器的元素不可见
$browser->assertDialogOpened($message)
断言带给定字符串的JavaScript对话框已打开
$browser->assertEnabled($field)
断言给定字段是否启用
$browser->assertDisabled($field)
断言给定字段是否禁用
$browser->assertFocused($field)
断言给定字段是否获得焦点
$browser->assertNotFocused($field)
断言给定字段是否失去焦点
$browser->assertVue($property, $value, $component)
断言给定 Vue 组件数据与给定值匹配
$browser->assertVueIsNot($property, $value, $component)
断言给定 Vue 组件数据与给定值不匹配
$browser->assertVueContains($property, $value, $componentSelector = null)
断言给定Vue组件数据是否是一个数组并且包含给定值
$browser->assertVueDoesNotContain($property, $value, $componentSelector = null)
断言给定Vue组件数据是否是一个数组并且不包含给定值
页面
有时候,测试需要多个复杂动作在一个序列中执行,这会使得测试代码难以阅读和理解。页面允许你使用单个方法定义优雅的可以在给定页面执行的动作,页面还允许你定义指向应用或单个页面的通用选择器的快捷方式。
生成页面
要生成页面对象,使用 Artisan 命令 dusk:page 即可。所有页面对象都位于 tests/Browser/Pages 目录:
php artisan dusk:page Login
配置页面
默认情况下,页面有三个方法:url、assert 和 elements,下面我们来讨论 url 和 assert,至于 elements,我们将会在后续选择器速记中详细讨论。
url方法
url 方法会返回代表页面的 URL 路径,Dusk 会在浏览器中导航到页面时使用这个 URL:
/**
* Get the URL for the page.
* @return string
*/
public function url()
return '/login';
assert方法
assert 方法会生成必要的断言来验证浏览器确实在给定页面,完成这个方法不是必须的;不过,你可以在需要的时候生成这些断言。这些断言将会在导航到页面时自动运行:
/**
* Assert that the browser is on the page.
* @return void
*/
public function assert(Browser $browser)
$browser->assertPathIs($this->url());
导航到页面
页面被配置后,可以使用 visit 方法导航到该页面:
use Tests\Browser\Pages\Login;
$browser->visit(new Login);
有时候,你可能已经在给定页面上了,并且需要“加载”页面选择器和方法到当前测试上下文,这在点击按钮以及重定向到给定页面时很常见。在本例中,我们能可以在加载页面时使用 on 方法:
use Tests\Browser\Pages\CreatePlaylist;
$browser->visit('/dashboard')
->clickLink('Create Playlist')
->on(new CreatePlaylist)
->assertSee('@create');
速记选择器
页面的 elements 方法允许你为页面的 CSS 选择器定义快速的、易记的快捷方式,例如,让我们为应用登录页面的“email”输入定义一个快捷方式:
/**
* Get the element shortcuts for the page.
* @return array
*/
public function elements()
return [
'@email' => 'input[name=email]',
];
现在,你可以在任意你想要试用完整CSS选择器的地方使用速记选择器:
$browser->type('@email', 'xueyuanjun@laravelacademy.org');
全局速记选择器
安装完 Dusk 后,一个基本的 Page 类会生成到 tests/Browser/Pages 目录下。该类包含一个可用于定义全局速记选择器的 siteElement 方法,所谓全局速记选择器,指的是在整个应用中生效的速记选择器:
/**
* Get the global element shortcuts for the site.
* @return array
*/
public static function siteElements()
return [
'@element' => '#selector',
];
页面方法
除了页面定义的默认方法外,你还可以定义额外的方法用于测试。例如,假设我们正在构建一个音乐管理应用,应用页面常用的功能就是创建一个播放列表,我们不必在每次测试的时候重复编写创建播放列表的逻辑,只需在页面类中定义一个 createPlaylist 方法即可:
<?php
namespace Tests\Browser\Pages;
use Laravel\Dusk\Browser;
class Dashboard extends Page
// Other page methods...
/**
* Create a new playlist.
* @param \Laravel\Dusk\Browser $browser
* @param string $name
* @return void
*/
public function createPlaylist(Browser $browser, $name)
$browser->type('name', $name)
->check('share')
->press('Create Playlist');
定义好方法后,可以在任意使用该页面的测试中使用,浏览器实例会自动传递给页面方法:
use Tests\Browser\Pages\Dashboard;
$browser->visit(new Dashboard)
->createPlaylist('My Playlist')
->assertSee('My Playlist');
组件
组件和 Dusk 的「页面对象」类似,只不过用于在整个应用中作为可复用的 UI 和功能片段,例如导航条或通知窗口。因此,组件并不与特定 URL 绑定。
生成组件
要生成组件,使用 Artisan 命令 dusk:component,新生成的组件位于 test/Browser/Components 目录下:
php artisan dusk:component DatePicker
如上所示,「日期选择器」是一个可以在整个应用的不同页面有效的示例组件。手动编写浏览器自动测试逻辑在测试套件的各个测试中选择日期会显得很笨拙,所以,我们可以定义一个 Dusk 组件来表示这个日期选择器,从而方面我们在单个可复用组件中实现相应业务逻辑:
<?php
namespace Tests\Browser\Components;
use Laravel\Dusk\Browser;
use Laravel\Dusk\Component as BaseComponent;
class DatePicker extends BaseComponent
/**
* Get the root selector for the component.
* @return string
*/
public function selector()
return '.date-picker';
/**
* Assert that the browser page contains the component.
* @param Browser $browser
* @return void
*/
public function assert(Browser $browser)
$browser->assertVisible($this->selector());
/**
* Get the element shortcuts for the component.
* @return array
*/
public function elements()
return [
'@date-field' => 'input.datepicker-input',
'@month-list' => 'div > div.datepicker-months',
'@day-list' => 'div > div.datepicker-days',
];
/**
* Select the given date.
* @param \Laravel\Dusk\Browser $browser
* @param int $month
* @param int $year
* @return void
*/
public function selectDate($browser, $month, $year)
$browser->click('@date-field')
->within('@month-list', function ($browser) use ($month) {
$browser->click($month);
})
->within('@day-list', function ($browser) use ($day) {
$browser->click($day);
});
使用组件
定义好组件后,就可以在任何测试中通过日期选择器轻松选择日期,使用组件还有一个好处就是,如果选择日期的必要逻辑有改动,只需更新这个组件即可:
<?php
namespace Tests\Browser;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Tests\Browser\Components\DatePicker;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends DuskTestCase
/**
* A basic component test example.
* @return void
*/
public function testBasicExample()
$this->browse(function (Browser $browser) {
$browser->visit('/')
->within(new DatePicker, function ($browser) {
$browser->selectDate(1, 2018);
})
->assertSee('January');
});
持续集成
CircleCI
如果你想通过 CircleCI 运行 Dusk 测试,可以使用这个配置文件作为起点,和 Travis CI 一样,我们使用 php artisan serve 命令启动 PHP 自带的 Web 服务器:
version: 2
jobs:
build:
steps:
- run: sudo apt-get install -y libsqlite3-dev
- run: cp .env.testing .env
- run: composer install -n --ignore-platform-reqs
- run: npm install
- run: npm run production
- run: vendor/bin/phpunit
- run:
name: Start Chrome Driver
command: ./vendor/laravel/dusk/bin/chromedriver-linux
background: true
- run:
name: Run Laravel Server
command: php artisan serve
background: true
- run:
name: Run Laravel Dusk Tests
command: php artisan dusk
- store_artifacts:
path: tests/Browser/screenshots
Codeship
想要在 Codeship 中运行 Dusk 测试,添加下面的命令到 Codeship 项目,当然,这些命令这是一个入门示例,如果需要的话你可以添加更多额外命令:
phpenv local 7.2
cp .env.testing .env
mkdir -p ./bootstrap/cache
composer install --no-interaction --prefer-dist
php artisan key:generate
nohup bash -c "php artisan serve 2>&1 &" && sleep 5
php artisan dusk
Heroku CI
要想在 Heroku CI 上运行 Dusk 测试,添加以下 Google Chrome buildpack 和 脚本到 Heroku 的 app.json 文件中:
"environments": {
"test": {
"buildpacks": [
{ "url": "heroku/php" },
{ "url": "https://github.com/heroku/heroku-buildpack-google-chrome" }
],
"scripts": {
"test-setup": "cp .env.testing .env",
"test": "nohup bash -c './vendor/laravel/dusk/bin/chromedriver-linux > /dev/null 2>&1 &' && nohup bash -c 'php artisan serve > /dev/null 2>&1 &' && php artisan dusk"
Travis CI
要想通过 Travis CI 运行 Dusk 测试,可以使用下面这个 .travis.yml 配置。由于 Travis CI 并不是一个图形化的环境,我们还需要一些额外的操作步骤以便启动 Chrome 浏览器。此外,我们将会使用 php artisan serve 来启动 PHP 自带的 Web 服务器:
language: php
php:
- 7.3
addons:
chrome: stable
install:
- cp .env.testing .env
- travis_retry composer install --no-interaction --prefer-dist --no-suggest
- php artisan key:generate
before_script:
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &
- php artisan serve &
script:
- php artisan dusk
Github Actions
如果你使用 Github Actions 来运行 Dusk 测试,可以使用下面这个配置文件作为起点。和 Travis CI 类似,我们使用 php artisan serve 命令来启动 PHP 内置的 Web 服务器:
name: CI
on: [push]
jobs:
dusk-php:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Prepare The Environment
run: cp .env.example .env
- name: Install Composer Dependencies
run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
- name: Generate Application Key
run: php artisan key:generate
- name: Upgrade Chrome Driver
run: php artisan dusk:chrome-driver
- name: Start Chrome Driver
run: ./vendor/laravel/dusk/bin/chromedriver-linux > /dev/null 2>&1 &
- name: Run Laravel Server
run: php artisan serve > /dev/null 2>&1 &
- name: Run Dusk Tests
run: php artisan dusk
在 .env.testing 文件中,调整 APP_URL 值如下:
APP_URL=http://127.0.0.1:8000
选择器
持续集成
组件
Vue
对话框
鼠标
键盘
上传文件
表单
链接
Laravel
交互
元素
ChromeDriver
Selenium
Dusk
浏览器
测试
文档
6.0
点赞
取消点赞
收藏
取消收藏
赞赏
分享到以下平台:
<< 上一篇:
HTTP 测试
>> 下一篇:
控制台测试
无评论
登录后即可添加评论
升级为学院君订阅用户(新年优惠🎁)
内容导航
简介
安装
管理 ChromeDriver 安装
使用其它浏览器
快速入门
生成测试
运行测试
环境处理
创建浏览器
浏览器宏
认证
数据库迁移
与页面元素交互
Dusk 选择器
点击链接
文本、值 & 属性
使用表单
上传文件
使用键盘
使用鼠标
JavaScript 对话框
选择器作用域
等待元素
Vue 断言
有效的断言
页面
生成页面
配置页面
导航到页面
速记选择器
页面方法
组件
生成组件
使用组件
持续集成
CircleCI
Codeship
Heroku CI
Travis CI
Github Actions
相关推荐
浏览器测试:使用 Laravel Dusk 进行浏览器测试
Laravel 5.5 中文文档
测试
浏览器测试
Laravel 5.6 中文文档
测试
浏览器测试(Laravel Dusk)
Laravel 5.7 中文文档
测试系列
浏览器测试
Laravel 5.8 中文文档
测试系列
基于 Laravel Dusk 进行浏览器测试
Laravel 8 中文文档
测试系列
回到顶部
2022 基于 Laravel 6 构建
关于学院
订阅服务
友情链接
站点地图
本站 CDN 加速服务由又拍云赞助