
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、前回は「 Laravel + React のメール送信 Featureテストをつくる 」という記事を公開しました。
そして、この記事内でのテストにはある特徴があります。
それは・・・・・・
擬似的なテスト
というものです。
つまり、ブラウザを操作「したことにする」テストということです。
もちろん、コードベースのテストでも充分確認できるでしょうし、開発内容によって「そこまでする必要はない」場合も多いとは思うのですが、せっかく記事を書いたので「ブラウザを使ったテスト」もやってみたくなりました。
なお、ブラウザテストと言えば少し前までSelenium
が有名でしたが、なんとLaravel
にはChrome
を使ったブラウザテストが簡単に実装できる「Laravel Dusk」という機能があります(しかも、Selenium
との連携もできるようです)
そこで
今回は「Laravel + React」でつくったお問い合わせフォームで「ブラウザテスト」を実装してみましょう
ぜひ何かの参考になりましたら嬉しいです。
「ドアが開いてたから
デパートに入ったら、
すでに閉店済みで閉じ込められました」
開発環境: Laravel 9.x、React、Vite、Inertia.js、TailwindCSS
前提として
今回も前回記事でも使った Laravel + React でお問い合わせフォームをつくる という記事のお問い合わせフォームを使って「ブラウザテスト」を作っていきます。
ただし、フォーム内の<input>
などの入力にid
やname
がついていないので以下のように変更しておいてください。(これは、セレクタを指定して入力やボタンクリックをするため必要です)
resources/js/Pages/Contact/Create.jsx
// 省略
export default function Create(props) {
// 省略
return (
<div className="p-5">
<h1>お問い合わせフォーム</h1>
<div className="border p-4 bg-gray-50 w-full md:w-1/2">
<div className="mb-3">
<FormLabel required>お問い合わせの種類</FormLabel>
<select name="subject_id" className="form-control text-smw-full md:w-1/2" value={subjectId} onChange={e => setSubjectId(e.target.value)}>
<option value="">▼ 選択してください</option>
{contactTypes.length > 0 && contactTypes.map(contactType => (
<option key={contactType.id} value={contactType.id}>{contactType.name}</option>
))}
</select>
<ErrorMessage message={errors.subject_id}></ErrorMessage>
</div>
<div className="mb-3">
<FormLabel required>お名前</FormLabel>
<input name="name" type="text" className="w-full md:w-1/2" value={name} onChange={e => setName(e.target.value)} />
<ErrorMessage message={errors.name}></ErrorMessage>
</div>
<div className="mb-3">
<FormLabel required>メールアドレス</FormLabel>
<input name="email" type="email" className="w-full md:w-1/2" value={email} onChange={e => setEmail(e.target.value)} />
<ErrorMessage message={errors.email}></ErrorMessage>
</div>
<div className="mb-3">
<FormLabel required>お問い合わせ内容</FormLabel>
<textarea name="body" className="form-control w-full block" rows="5" value={message} onChange={e => setMessage(e.target.value)}></textarea>
<ErrorMessage message={errors.message}></ErrorMessage>
</div>
<div className="mb-3">
<FormLabel>URL</FormLabel>
<input name="url" type="text" className="w-full md:w-1/2" value={url} onChange={e => setUrl(e.target.value)} />
<ErrorMessage message={errors.url}></ErrorMessage>
</div>
<button
id="submit"
type="button"
className="text-white bg-blue-700 font-medium rounded text-sm px-5 py-2.5 mr-2 mb-2" onClick={handleSubmit}>
送信する
</button>
</div>
</div>
)
}
ちなみに見た目は以下の通りそのままです。
パッケージをインストールする
では、Laravel Dusk
をインストールしていきます。
以下のコマンドを実行してください。
composer require --dev laravel/dusk
パッケージのインストールが完了したら、続けて以下のコマンドを実行します。
php artisan dusk:install
すると、tests/Browser
というフォルダが作成され、この中にいろいろなサンプルコードが用意されます。
【注意】ちなみに、もちろんですがGoogle Chrome
はインストールしておいてくださいね。
では、この中にブラウザテストを作っていきましょう
テストコードを作っていく
では、今回のメインになる部分を作っていきましょう。
以下のコマンドを実行してください。
php artisan dusk:make ContactTest
すると、ファイルが作成されるので中身を次のように変更します。
tests/Browser/ContactTest.php
<?php
namespace Tests\Browser;
use App\Enums\ContactType;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ContactTest extends DuskTestCase
{
public function test_can_send_contact_message()
{
$this->browse(function (Browser $browser) {
$date_time = now()->format('Ymd_His');
$screenshot_filename = 'test_can_send_contact_message_'. $date_time;
$subject_id = ContactType::Question->value;
$browser
// ページ移動
->visit('/contact/create')
// レンダリングを待つ
->pause(3000)
// 各データをセット
->select('subject_id', $subject_id)
->type('name', 'テストユーザー')
->type('email', 'taro@example.com')
->type('body', "テストメッセージです。\nよろしくお願いします。")
->type('url', 'https://example.com')
// スクリーンショットを取る(1)
->screenshot($screenshot_filename .'_1')
// 送信
->click('#submit')
->waitForDialog() // 確認ダイアログが表示されるまで待機
->acceptDialog() // OK を選択
// レンダリングを待つ
->pause(3000)
// スクリーンショットを取る(2)
->screenshot($screenshot_filename .'_2')
->assertRouteIs('contact.complete'); // 完了ページへ移動したか確認する
});
}
}
この中で重要な部分は、以下2つです。
まず、$browser->value('selector', 'value');
でも<input>
へ入力できますが、React
が反応しないため$browser->type('name', 'value');
を使う必要があります。(おそらくVue
などJavaScript
メインで動くページも同じだと思います)
もう1つは、click()
の直後に2つメソッドをつなげていますが、これはクリックすると以下のような確認ダイアログが出るので、その際「OK」ボタンを選択している、という意味になります。
これで作業は完了です。
お疲れ様でした
(ブラウザテストの)テストをしてみる
では、実際にテストをしてみましょう
以下のコマンドを実行してください。
php artisan dusk tests/Browser/ContactTest.php
※ なお、シンプルにphp artisan dusk
だけでも実行できますが、すべてのブラウザテストが実行されます。
すると、どうなったでしょうか・・・・・・
まず、コマンドにはテストがうまくいったことが表示されました。
そして、tests/Browser/screenshots/
フォルダの中に画像が2つ作成されています。
まず1つ目を確認してみましょう。
はい
うまく選択&入力が実行されてた様子がスクリーンショットになっています。
ではもう1つです。
はい
メール送信が完了したページが画像化されていました。
成功です
では最後に、メールがちゃんと送信されてるかもチェックしておきましょう。
どうなったでしょうか・・・・・・
はい
さっきLaravel Dusk
でセットした内容が送信されていました。
すべて成功です
企業様へのご提案
今回のようなブラウザテストを利用すると、まずシンプルに以下のようなメリットがあります。
- 開発時: バグの少ないシステムをつくることができる
- アップデート時: 過去のコードに影響が出ていないかをチェックできる
つまり、開発時だけでなく開発後でもこういったテストを作っておくことは今後にとってプラスになるといっていいでしょう。
また、上記だけではなくブラウザを使っていることで以下のメリットも受けることが出来ます。
- 実際のブラウザでの動きを確認できる(JavaScript のテストができる)
- ブラウザの確認作業を自動化(=時短化)できる
- スクリーンショットがあるので実際の見た目もチェックできる
※ なお、ブラウザテストのデメリットとしてはブラウザを起動したりページの描画を待たないといけない場合があるため、テストの実行自体には時間がかかるという点です。
もしブラウザテストだけでなく、コードのみのテストもご準備になりたいようでしたら、ぜひお気軽にご相談ください。
お待ちしております。
おわりに
ということで、今回は「Laravel + React」のブラウザテストをLaravel Dusk
で作ってみました。
いつも思いますが、こういう「カユイところに手が届く」だけでなく「オロナインH軟膏まで塗ってくれる」ようなLaravel
のいたれりつくせりにはいつも感動させられます。
(実際のところはまったく知りませんが)こういった機能の開発者さんたちには、ぜひぜひたくさんお金を儲けていただいて、いい生活をしていてほしいものです。
私もいつかはそうなりないものですね(笑)
ではでは〜
「鼻呼吸で寝られるように
トレーニング中です 」