Laravel Dusk测试失败时如何发邮件?特定测试失败时如何执行函数或发带截图邮件?
嘿,我来分享两个针对Laravel Dusk测试失败场景的实用方案,都是我平时项目里用过的,亲测靠谱!
1. 所有Dusk测试失败时自动发送邮件
这个需求可以通过监听Dusk内置的TestFailed事件来实现,结合Laravel的邮件系统就能轻松搞定:
第一步:创建失败通知邮件类
先运行Artisan命令生成邮件类:php artisan make:mail TestFailureNotification然后在生成的
App\Mail\TestFailureNotification类里,接收测试失败的详情数据:namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class TestFailureNotification extends Mailable { use Queueable, SerializesModels; public $failureDetails; public function __construct($failureDetails) { $this->failureDetails = $failureDetails; } public function build() { return $this->subject('Laravel Dusk 测试失败通知') ->view('emails.test-failure'); } }第二步:编写邮件视图
在resources/views/emails/test-failure.blade.php里添加展示失败详情的内容:<h2>Dusk测试失败啦!</h2> <ul> <li>测试类:{{ $failureDetails['test_class'] }}</li> <li>测试方法:{{ $failureDetails['test_method'] }}</li> <li>错误信息:{{ $failureDetails['error_message'] }}</li> <li>失败时间:{{ $failureDetails['failure_time'] }}</li> </ul>第三步:注册事件监听器
打开App\Providers\DuskServiceProvider,在boot方法里监听TestFailed事件:use Illuminate\Support\Facades\Mail; use Laravel\Dusk\Events\TestFailed; public function boot() { parent::boot(); $this->app['events']->listen(TestFailed::class, function (TestFailed $event) { $failureDetails = [ 'test_class' => $event->test, 'test_method' => $event->method, 'error_message' => $event->exception->getMessage(), 'failure_time' => now()->toDateTimeString(), ]; // 替换成你的告警邮箱 Mail::to('dev-alerts@yourdomain.com')->send(new \App\Mail\TestFailureNotification($failureDetails)); }); }这样一来,任何Dusk测试失败时,都会自动触发邮件通知。
2. 特定测试失败时执行指定函数/发送带截图的邮件
如果只需要针对特定测试做定制化处理,可以用Dusk测试类的onFailure钩子,或者在全局事件监听里增加判断逻辑。
2.1 执行指定函数
比如我们想在testCheckoutFlow测试失败时,调用自定义的告警函数:
use Laravel\Dusk\TestCase as BaseTestCase; class CheckoutFlowTest extends BaseTestCase { protected function onFailure($exception) { // 获取当前执行的测试方法名 $currentTestMethod = $this->getName(); // 判断是否是目标测试方法 if ($currentTestMethod === 'testCheckoutFlow') { $this->sendCustomAlert($exception); } // 不要忘记调用父类方法,保证默认的失败逻辑(比如生成截图)正常执行 parent::onFailure($exception); } private function sendCustomAlert($exception) { // 这里写你的自定义逻辑:比如调用外部告警API、写入紧急日志等 \Log::critical('【紧急】结账流程测试失败', [ 'error' => $exception->getMessage(), 'test_method' => 'testCheckoutFlow' ]); // 也可以在这里调用其他业务函数,比如暂停相关自动化流程 // $this->pauseCheckoutAutomation(); } public function testCheckoutFlow() { $this->browse(function ($browser) { $browser->visit('/checkout') ->type('email', 'test@example.com') ->press('提交订单') ->assertSee('订单已确认'); // 假设这个断言会触发失败 }); } }
2.2 发送附带截图的邮件
Dusk默认会在测试失败时生成截图,存放在tests/Browser/screenshots目录。我们可以把截图作为附件发送:
use Illuminate\Support\Facades\Mail; use Laravel\Dusk\TestCase as BaseTestCase; class CheckoutFlowTest extends BaseTestCase { protected function onFailure($exception) { $currentTestMethod = $this->getName(); if ($currentTestMethod === 'testCheckoutFlow') { // 获取自动生成的截图路径 $screenshotPath = $this->screenshotPath(); $failureDetails = [ 'test_class' => static::class, 'test_method' => $currentTestMethod, 'error_message' => $exception->getMessage(), ]; // 发送带附件的邮件 Mail::to('dev-alerts@yourdomain.com')->send( new \App\Mail\TestFailureWithScreenshotNotification($failureDetails, $screenshotPath) ); } parent::onFailure($exception); } }
对应的邮件类需要支持附件:
namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class TestFailureWithScreenshotNotification extends Mailable { use Queueable, SerializesModels; public $details; public $screenshotPath; public function __construct($details, $screenshotPath) { $this->details = $details; $this->screenshotPath = $screenshotPath; } public function build() { return $this->subject('Dusk测试失败:'.$this->details['test_method']) ->view('emails.test-failure-with-screenshot') ->attach($this->screenshotPath, [ 'as' => 'test-failure-screenshot.png', 'mime' => 'image/png', ]); } }
额外提示:全局监听特定测试
如果不想在每个测试类里写onFailure,也可以在DuskServiceProvider的事件监听里增加判断:
$this->app['events']->listen(TestFailed::class, function (TestFailed $event) { // 判断是否是目标测试 if ($event->test === \Tests\Browser\CheckoutFlowTest::class && $event->method === 'testCheckoutFlow') { $screenshotPath = $event->browser?->screenshotPath(); // 执行自定义逻辑或发送带截图的邮件 } });
内容的提问来源于stack exchange,提问作者Randika
相关产品推荐
相关产品推荐

