You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:39:59