Playwrightを説明する必要にかられて作成。
なお、本記事の利用用途はE2Eテストではなく、ただのブラウザ操作自動化です。
前提としてNode.js 12以上が必要です。そちらの説明は「NVM for Windowsを使って複数バージョンのnodejsをインストール」をご覧ください。
前準備
実験用にtest-playwrightディレクトリを作ります。今後はこのディレクトリで作業します。
>mkdir test-playwright && cd test-playwright
Playwrightのインストール
npmを使ってインストール
>npm install playwright added 2 packages in 2s
package.jsonやnode_modulesディレクトリなどが生成されます。
バージョン確認
>npx playwright --version Version 1.31.2
Playwrightのデモ
Yahoo! JAPANを開く
> npx playwright codegen "https://www.yahoo.co.jp"
Yahoo! Japanを開いた状態でChromium とPlaywright Inspector の2つが起動
Playwright Inspectorウィンドウの Target: 「Test Runner」を「Library」に変更
Chromium(Yahoo! Japan)を以下の手順でマウス操作してみます。
- 検索フォームから「Google」とタイプして検索
- 検索結果からGoogleをクリック
- Googleの検索フォームに「Yahoo」とタイプして検索
- Googleの検索結果からYahoo! JAPANをクリック
上記の手順が済んだらPlaywright Inspectorで生成されたコードを確認
※Chromiumを閉じるとPlaywright Inspectorまで一緒に閉じてしまうので注意
出来上がったコード(下記参照)をコピーし、yahoo.cjs と名付けてUTF-8で保存
const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://www.yahoo.co.jp/'); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click(); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google'); await page.getByRole('button', { name: '検索' }).click(); await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click(); await page.getByRole('combobox', { name: '検索' }).click(); await page.getByRole('combobox', { name: '検索' }).fill('Yahoo'); await page.getByRole('combobox', { name: '検索' }).press('Enter'); await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click(); // --------------------- await context.close(); await browser.close(); })();
上記コードを実行
>node yahoo.cjs
Chromiumが立ち上がり、「Yahoo検索→Google検索→Yahooへ」の操作を自動で行う
スクリーンショットを撮る1行を追加
const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://www.yahoo.co.jp/'); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click(); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google'); await page.getByRole('button', { name: '検索' }).click(); await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click(); await page.getByRole('combobox', { name: '検索' }).click(); await page.getByRole('combobox', { name: '検索' }).fill('Yahoo'); await page.getByRole('combobox', { name: '検索' }).press('Enter'); await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click(); // ここに1行追加しました await page.screenshot({ path : 'yahoo.png'}); // --------------------- await context.close(); await browser.close(); })();
ちなみに、以下のコメントアウトした部分がなくても動きます(マウスのために入った余計な操作なので)
const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://www.yahoo.co.jp/'); //await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click(); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google'); await page.getByRole('button', { name: '検索' }).click(); await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click(); //await page.getByRole('combobox', { name: '検索' }).click(); await page.getByRole('combobox', { name: '検索' }).fill('Yahoo'); await page.getByRole('combobox', { name: '検索' }).press('Enter'); await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click(); await page.screenshot({ path : 'yahoo.png'}); // --------------------- await context.close(); await browser.close(); })();
headless: falseをtrueに変更するとヘッドレスモード(Chromiumを画面非表示)で実行
const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ // ここです headless: true }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://www.yahoo.co.jp/'); //await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).click(); await page.getByRole('searchbox', { name: '検索したいキーワードを入力してください' }).fill('Google'); await page.getByRole('button', { name: '検索' }).click(); await page.getByRole('link', { name: 'Google https://www.google.com ...' }).click(); //await page.getByRole('combobox', { name: '検索' }).click(); await page.getByRole('combobox', { name: '検索' }).fill('Yahoo'); await page.getByRole('combobox', { name: '検索' }).press('Enter'); await page.getByRole('link', { name: 'Yahoo! JAPAN Yahoo! JAPAN https://www.yahoo.co.jp' }).click(); await page.screenshot({ path : 'yahoo.png'}); // --------------------- await context.close(); await browser.close(); })();
ざっくりこんな感じ
const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext(); const page = await context.newPage(); await page.goto('https://www.example.jp/'); // ここからやりたいことを書く フォームを入力したり、プルダウンから選択したり スクリーンショットを撮ったり、ボタンを押したり // ここまで await browser.close(); })();
codegenで作成したコードのため、『「検索」ボタンをクリック』のような記述になっていますが、本来はdata-testid属性を用いて、HTML側で<button data-testid="search">検索</button>
、 Playwright側でawait page.getByTestId('search').click();
とする記述が望ましいようです。
参考
- Playwright
- Locators#locate-by-test-id
- これだけはおさえておきたいPlaywrightコマンド集
- なぜE2Eテストでidを使うべきではないのか