ごった煮
docker: seleniumコンテナはどのイメージを使えばいいか
最新版のだとダメだった。
いろいろ試して selenium/standalone-chrome:3.141.59-oxygen が上手く動作した。
(duskのバージョンにも依存するのか?)
ポートは 4444:4444 でok
RemoteWebDriver には http://{seleniumコンテナのname}:4444/wd/hub を指定
テスト毎に初期レコードを投入した状態にロールバックする
達成したい目標は「テストが終わるたびにいくつかの初期レコードを投入した状態に戻したい」というもの。
具体的にはマスタテーブルにある程度のレコードを入れたいとか、ログイン用のユーザを作っておくとか。
しかし、デフォルトの DatabaseTransactions, DatabaseMigrations, RefreshDatabase では上手く達成できなかった。
もうめんどくさいから投入したいレコードを SQL ファイルでまとめて読み込むようにした方が早いんじゃないかと思う。
storageの配下に以下の物を配置します。
- storage/tests/init.sql: テーブルをCREATEしたり初期レコードをINSERTするSQL
- storage/tests/migrations/InitializeDb.php: SQLを用いてDBを初期化するマイグレーションファイル
use Illuminate\Support\Facades\DB; use Illuminate\Database\Migrations\Migration; class InitializeDb extends Migration { /** * Run the migrations. * * @return void */ public function up() { DB::unprepared(file_get_contents(storage_path('tests/init.sql'))); } /** * Reverse the migrations. * * @return void */ public function down() { // } }
上記ファイルを用いてマイグレーションするため、DatabaseMigrations を継承して runDatabaseMigrations 関数をオーバーライドします。
// tests/DatabaseMigrations.php trait DatabaseMigrations { use BaseDatabaseMigrations; /** * Refresh a conventional test database. * * @return void */ protected function runDatabaseMigrations() { $this->artisan('migrate:fresh', [ '--path' => storage_path('tests/migrations'), '--realpath' => 1, ]); $this->app[Kernel::class]->setArtisan(null); $this->beforeApplicationDestroyed(function () { RefreshDatabaseState::$migrated = false; }); } }
テスト毎にcookieを初期化
ログイン状態が継続してしまったりするので、cookieをテスト完了ごとにきっちり削除する。
DuskTestCaseの setUp() に以下を記述します。
public function setUp() : void { parent::setUp(); foreach (static::$browsers as $browser) { $browser->driver->manage()->deleteAllCookies(); } }
プルダウンのoptionのvalueを取得する
WebElement に対して findElements (または findElement) するだけ
use Facebook\WebDriver\WebDriverBy; $this->browse(function (Browser $browser) { $select = $browser->element('select[name="area_id"]'); $options = $select->findElements(WebDriverBy::cssSelector('option:not([disabled])')); $values = collect([]); foreach ($options as $option) { $value = (int) $option->getAttribute('value'); $values->push($value); } });
elementのテキスト部分が取得したい
$element->getText()
CSSセレクタでand条件使いたい
[] を連立するとできた
$element->findElements(WebDriverBy::cssSelector('input[type="hidden"][name$="[token]"]'));
selectタグの特定optionを選択させたい
ラベルを sendKeys で指定
$element->findElements(WebDriverBy::cssSelector('select[name$="[pref]"]'))->sendKeys('東京都');