Laravel Dusk テストコード作成時の困った場合の対処法


Laravel dusk でブラウザテストを作成していて困った部分の対処法のメモです。
間違っている箇所があればご指摘いただければ幸いです。

dusk失敗時の画面スクリーンショット

app\tests\Browser\screenshots配下に失敗時の画面スクリーンショットが作成されます。

要素の表示をwaitで待つ

$browser->waitForText('検索', 30);
$browser->waitFor("#search", 30);

jsで子画面に表示される要素がクリックできないとき

素のjsで要素をクリックする(サービスプロバイダにマクロを登録する 参照)

//クリックする
$browser->clickToElement(".search_btn");

画面内に表示されていない要素がクリックできないとき

素のjsで要素にスクロールする(サービスプロバイダにマクロを登録する 参照)

//クリックする
$browser->scrollToElement(".search_btn");

サービスプロバイダにマクロを登録する

ブラウザマクロを作成し、サービスプロバイダにマクロを登録する。

[参考]
https://readouble.com/laravel/5.7/ja/dusk.html (ブラウザマクロ 部分参照)
https://readouble.com/laravel/5.3/ja/providers.html (プロバイダの登録 部分参照)
https://github.com/laravel/dusk/issues/203 (マクロ登録例)

<?php
namespace App\Providers;

use Laravel\Dusk\Browser;
use Illuminate\Support\ServiceProvider;

class DuskServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        Browser::macro('scrollToElement', function ($element = null) {
            $this->script("$('html, body').animate({ scrollTop: $('$element').offset().top }, 0);");

            return $this;
        });

        Browser::macro('clickToElement', function ($element = null) {
            $this->script("document.querySelector('$element').click();");

            return $this;
        });

        Browser::macro('switchFrame', function ($frame = null) {
            if ($frame) {
                $this->driver->switchTo()->defaultContent()->switchTo()->frame($frame);
            } else {
                // Main frame
                $this->driver->switchTo()->defaultContent();
            }
            return $this;
        });
    }
}
config/app.php
'providers' => [
    // Other Service Providers

    App\Providers\DuskServiceProvider::class,
],

Class 'App\Providers\DuskServiceProvider' not found登録したマクロが見つからないというエラーが表示された場合、キャッシュファイルを削除すること。

artisan cache:clear
artisan config:clear
artisan route:clear
artisan view:clear

testの中断(Ctrl + c)でDB接続先がずれた?

.env / .env.dusk.local(.env.dusk.{environment}) の中身を確認する。
テスト中は.envの内容が一時backupファイルに退避され、.env.dusk.localの内容が.envに書き込まれるようですが、
中断により.envの内容が.env.dusk.localのまま、backupファイルが残った状態という現象が私のDockerテスト環境では起こりました。
.envを戻し、backupファイルを削除すると戻ります。
(そしてキャッシュファイルも削除)

chromeの設定ファイル (UAを変えたい 画面サイズを変更したいなどはここで)

DuskTestCase.php

    protected function driver()
    {
        $options = (new ChromeOptions)->addArguments([
            '--disable-gpu',
            '--headless',
            '--window-size=375,667',
            '--no-sandbox',
            '--lang=ja_JP',
            '--disable-dev-shm-usage'
        ]);

        $ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.91 Mobile/15E148 Safari/605.1';
        $options->setExperimentalOption('mobileEmulation', ['userAgent' => $ua]);

        return RemoteWebDriver::create(
            'http://selenium:4444/wd/hub', DesiredCapabilities::chrome()->setCapability(
                ChromeOptions::CAPABILITY, $options
            )
        );
    }

head部分のテスト

duskはcssセレクターで検証しようとすると先頭に'body'がつくため、bodyタグより上の要素の検証をしたい場合はこの書き方で

 $browser->assertSourceHas("<meta name=\"description\" content=\"Qiitaは情報満載!\">");

xpathを使って要素の値を取り出すことも可能

use Laravel\Dusk\Browser;
use Facebook\WebDriver\WebDriverBy; //xpath用
略
$browser->driver->findElement(WebDriverBy::xpath("//link[@rel='canonical']"))->getAttribute('href')

Rspec の before after のようなものを実装したい

[参考]
https://cpoint-lab.co.jp/article/201812/7155/

public function setUp() :void
{
    parent::setUp();
    // テストデーターの準備などを行う
}

PHPUnitのアサーションも使えます

$this->assertEquals($element_count, 50);

セッションの破棄

  $browser->driver->manage()->deleteAllCookies();

function日本語化(@testつける)

/**
 * @test
 */
public function ステータステスト()
{
    $res = $this->get("url");
    $res->assertStatus(200);
}

テストをグループ化して実行 (@group アノテーションでグループ化)

php artisan dusk tests/Browser/ --group samplegroup

/**
 * @group samplegroup
 */
public function sampleTest()
{
   //処理

テストをファイル単位で実行

php artisan dusk tests/Browser/SampleTest.php

Factoryで作成したデーターをテスト実行前に書き換える方法

$this->test_data->fill(["time" => "9:00"])->save();
複数でもOK
$data = ["status" => 1, "time" => "9:00", "end_time" => "10:00"];
$this->test_data->fill($data)->save();

The MAC is invalid.

暗号化キーを再生成する → php artisan key:generate
※暗号化したパスワードが複号できなくなるので取り扱い注意
[引用]
https://error-search.com/error-post/detail/144/The%2BMAC%2Bis%2Binvalid.

APP_DEBUG=true のデバックモードにしたままでテストを実行するとfailする

デバックバーが邪魔をして要素が見えていないため
APP_DEBUG=true は.env.dusk.localに入れない

HTML5 Form Validation ブラウザに依存するエラーメッセージがテストの邪魔をする

問題なければ、ブラウザ自動バリデーションを無効化してしまう

<form action="test.php" method="post" novalidate="novalidate">