dusk失败主因是环境、时机或可见性问题,而非代码错误:chromedriver与chrome主版本必须一致;visit后需用waitfor而非assertsee;ci中须强制headless并配置正确路径。

别把 Dusk 当成 PHPUnit 的延伸——它底层走的是 php-webdriver,操作的是真实 Chrome 实例,所有失败都卡在环境、时机或可见性上。
ChromeDriver 与 Chrome 版本不匹配导致 SessionNotCreatedException
这是本地运行 php artisan dusk 时最常遇到的崩溃点,错误信息通常是 Facebook\WebDriver\Exception\SessionNotCreatedException。根本不是代码写错了,而是 ChromeDriver 启动 Chrome 失败。
- 运行
chrome --version查看 Chrome 主版本(如124.0.6367.78) - 运行
chromedriver --version,只比对**主版本号**(如124),小版本不同一般可接受 - 不一致时:删掉
vendor/laravel/dusk/bin/chromedriver-mac(或对应平台文件),再执行php artisan dusk:install - Mac 上用 Homebrew 安装的 Chrome,二进制路径可能是
/opt/homebrew/bin/chrome,需在tests/DuskTestCase.php的driver()中显式指定:$options->addBinary('/opt/homebrew/bin/chrome')
visit() 后直接 assertSee() 总失败
visit() 只发导航请求,不等 HTML 解析、不等 JS 执行、不等 Vue/React 挂载。此时 DOM 可能为空,或文字还在 AJAX 响应里。
-
assertSee()检查的是当前 DOM 文本节点,对display: none、visibility: hidden或未挂载的组件完全无效 - 优先改用
waitForText('登录')或waitFor('.submit-btn', 10),显式等待文本或选择器出现 - Vue/React 页面建议加
->script('return window.appReady || false')等待应用就绪信号,比pause(500)更可靠 - 调试时加
->dump()->pause(),看实际 DOM 快照,比猜更准
CI 环境中 Dusk 白屏或超时
GitHub Actions / GitLab CI 默认无图形界面,Dusk 尝试启动 GUI Chrome 必然失败,且默认不启用 headless 模式。
- 必须在
tests/DuskTestCase.php的driver()方法中强制配置:--headless=new(Chrome 116+ 必须)、--no-sandbox、--disable-gpu - GitHub Actions 中不能只靠
actions/setup-node@v3,必须额外加上uses: browser-actions/setup-chrome@latest - 注释掉
DuskTestCase::prepare()中的static::startChromeDriver()—— CI 应由系统级服务或 action 启动 driver,而非 PHP 进程自己拉起 - Linux 环境下记得给
chromedriver赋执行权限:chmod +x vendor/laravel/dusk/bin/chromedriver-linux
如何跳过登录流程直接测后台页面
Dusk 浏览器请求和 PHPUnit 进程不在同一会话上下文,直接 Auth::login($user) 不会同步到浏览器 session。
- 最稳做法:在测试前生成带有效 session ID 的 URL,例如
/admin/products?token=xxx,配合中间件验证 token 并调用Auth::login($user) - 避免在
$this->browse()闭包内做Auth::login(),那只会作用于 PHPUnit 进程,对浏览器无效 - 若必须复用登录态,可在
beforeEach()中创建用户、生成 token、注入 cookie,并用$browser->cookie('laravel_session', $value)手动设置 - 注意:Laravel 10+ 默认使用
encrypt_cookies中间件,cookie 值需经Encrypter加密后才能被识别
复杂点不在写断言,而在判断“此刻页面是否真的 ready”——DOM 加载完、JS 执行完、CSS 渲染完、动画结束、网络请求返回,这些状态互不重叠,得靠 waitFor、script、assertVisible 组合判断,而不是依赖一个 assertSee。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











