Playwright は Microsoft が開発したブラウザ自動化ライブラリです。Selenium に比べて設定が少なく・自動待機が標準搭載で・モダンな書き方ができます。本記事ではインストールから最初のテスト実行まで、コマンド1つずつ丁寧に解説します。
📌 この記事の対象読者
| ✅ Playwright を初めて使う方 |
| ✅ Selenium は知っているが Playwright との違いを知りたい方 |
| ✅ ブラウザ操作を自動化して E2E テストを始めたい方 |
| ✅ Codegen(テストの自動録画)や Trace Viewer を試してみたい方 |
📖 この記事を読むとできること
| ✔ Playwright をインストールしてブラウザを起動できる |
| ✔ ページを開いてクリック・入力・アサーションができる |
| ✔ pytest-playwright を使ってテストを構造化できる |
| ✔ Codegen で操作を録画してテストコードを自動生成できる |
| ✔ スクリーンショット・Trace Viewer でデバッグできる |
筆者は複数のプロジェクトで Playwright を使った E2E テストを実践しています。
Selenium から Playwright に移行したプロジェクトもあり、両者の違いを実務の観点で比較できます。
本記事は「初日に動くテストを書く」を目標に、詰まりやすいポイントを先回りして解説します。
✅ この記事のゴール
- Playwright をインストールして
pytestでテストを実行できる状態 get_by_role・get_by_test_idなどのロケーターを使ってフォームを操作できる状態- Codegen でテストコードを自動生成できる状態
Playwright とは?Selenium との違い
| 比較項目 | Selenium | Playwright |
|---|---|---|
| ドライバー設定 | 別途必要(webdriver-manager 等) | ✅ インストール時に一括取得 |
| 自動待機 | 明示的待機(WebDriverWait)を自分で書く必要あり | ✅ 操作前に自動で待機(標準搭載) |
| ロケーター API | CSS・XPath・ID など | ✅ get_by_role 等の意味的 API も使える |
| 対応ブラウザ | Chrome / Firefox / Safari / Edge | Chromium(Chrome・Edge 含む)/ Firefox / WebKit |
| Codegen(録画) | なし(IDE プラグインは別途) | ✅ 標準搭載 |
| Trace Viewer | なし | ✅ テスト失敗の詳細を可視化 |
| 学習しやすさ | ○(資料・事例が豊富) | ◎(設定が少なく始めやすい) |
| 求人・採用実績 | ◎ 多い(歴史が長い) | ○ 増加中 |
新規プロジェクトなら Playwright が書きやすく安定しています。ただし求人数では Selenium がまだ多い状況です。Selenium の基本を学んでから Playwright に進むと、両方の強みを理解できます。
Playwright が急速に普及した理由
2020年以降、Playwright は E2E テストツールとして急速に普及しました。その背景には以下の理由があります。
| 理由 | 内容 |
|---|---|
| 自動待機が標準搭載 | Selenium のように WebDriverWait を毎回書く必要がなく、Flaky Test になりにくい |
| モダン SPA との相性 | React・Vue・Angular で作られた SPA を安定してテストできる |
| Codegen・Trace Viewer | デバッグと初期コード作成が格段にしやすい |
| ドライバー不要 | playwright install 一発でブラウザも揃い、設定コストが低い |
| CI との親和性 | GitHub Actions との組み合わせが公式でサポートされており導入しやすい |
Selenium から Playwright に移行したプロジェクトで最も変わったのは、WebDriverWait を書く回数が激減したことでした。Selenium 時代は「要素を取得する前に毎回待機条件を書く」のが当たり前でしたが、Playwright では操作メソッドが自動で待ってくれるため、テストコードがシンプルになりました。Flaky Test の発生頻度も明らかに下がりました。
① インストールする
まず Python 環境が用意できていることを確認してください(Python環境構築ガイド)。
venv を有効化した状態でインストールします。
# Playwright 本体と pytest プラグインをインストール
pip install playwright pytest-playwright
# ブラウザ本体のインストール(Chromium・Firefox・WebKit)
playwright install
インストール確認:
playwright --version
# Playwright 1.x.x と表示されれば OK
pip install だけでは動きません。
playwright install でブラウザ本体(Chromium 等)をダウンロードする必要があります。CI 環境でも同様です。② まず動かしてみる(スクリプト形式)
pytest を使う前に、まずシンプルなスクリプトで Playwright の動作を確認します。
# first_playwright.py
from playwright.sync_api import sync_playwright
def main() -> None:
with sync_playwright() as p:
# ブラウザを起動(headless=False でブラウザウィンドウを表示)
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# ページを開く
page.goto("https://example.com") # サンプルURL
# タイトルを確認
print(page.title())
# スクリーンショットを撮る
page.screenshot(path="screenshot.png")
browser.close()
if __name__ == "__main__":
main()
python first_playwright.py
ブラウザが開いてページが表示されれば成功です。screenshot.png も保存されます。
③ pytest でテストを書く
実務では pytest と組み合わせてテストを管理します。pytest-playwright をインストール済みなら、page fixture が自動で使えます。
最初のテストファイル
# test_first.py
from playwright.sync_api import Page, expect
def test_page_title(page: Page) -> None:
page.goto("https://example.com") # サンプルURL
assert "Example" in page.title()
# Playwright らしい書き方は expect を使う方法もある
# expect(page).to_have_title("Example Domain")
def test_heading_visible(page: Page) -> None:
page.goto("https://example.com") # サンプルURL
heading = page.get_by_role("heading", name="Example Domain")
expect(heading).to_be_visible() # Playwright らしい書き方
pytest test_first.py -v
正常な出力例:
========================= test session starts ==========================
collected 2 items
test_first.py::test_page_title PASSED [ 50%]
test_first.py::test_heading_visible PASSED [100%]
========================== 2 passed in 2.34s ==========================
ログインフォームのテスト(実践例)
# test_login.py
from playwright.sync_api import Page, expect
def test_login_success(page: Page) -> None:
page.goto("https://example.com/login") # サンプルURL
# メールアドレスを入力
page.get_by_label("メールアドレス").fill("user@example.com")
# パスワードを入力
page.get_by_label("パスワード").fill("password123")
# ログインボタンをクリック
page.get_by_role("button", name="ログイン").click()
# ダッシュボードに遷移したことを確認
expect(page).to_have_url("https://example.com/dashboard") # サンプルURL
def test_login_invalid_password(page: Page) -> None:
page.goto("https://example.com/login") # サンプルURL
page.get_by_label("メールアドレス").fill("user@example.com")
page.get_by_label("パスワード").fill("wrong-password")
page.get_by_role("button", name="ログイン").click()
# エラーメッセージが表示されることを確認
expect(page.get_by_test_id("error-message")).to_be_visible()
expect(page.get_by_test_id("error-message")).to_contain_text("パスワードが正しくありません")
④ expect でアサーションを書く
Playwright の expect は Web ページ向けに特化したアサーションで、条件が満たされるまで自動でリトライします。
| アサーション | 確認内容 |
|---|---|
expect(locator).to_be_visible() | 要素が表示されている |
expect(locator).to_be_hidden() | 要素が非表示 |
expect(locator).to_have_text("...") | 要素のテキストが指定値と一致する |
expect(locator).to_contain_text("...") | 要素のテキストに指定文字列が含まれる |
expect(locator).to_have_value("...") | input の値が指定値と一致する |
expect(locator).to_be_enabled() | 要素が有効状態(disabled でない) |
expect(locator).to_be_checked() | チェックボックスが ON |
expect(page).to_have_url("...") | ページの URL が指定値と一致する |
expect(page).to_have_title("...") | ページタイトルが指定値と一致する |
⑤ conftest.py でテストを整理する
ベース URL やブラウザ設定は conftest.py にまとめると、テストファイルをシンプルに保てます。
# conftest.py
import pytest
from playwright.sync_api import Page
BASE_URL = "https://example.com" # サンプルURL
@pytest.fixture
def logged_in_page(page: Page) -> Page:
"""ログイン済みの状態で page を返す fixture"""
page.goto(f"{BASE_URL}/login")
page.get_by_label("メールアドレス").fill("user@example.com")
page.get_by_label("パスワード").fill("password123")
page.get_by_role("button", name="ログイン").click()
page.wait_for_url(f"{BASE_URL}/dashboard")
return page
# test_dashboard.py
from playwright.sync_api import Page, expect
def test_dashboard_shows_username(logged_in_page: Page) -> None:
expect(logged_in_page.get_by_test_id("user-name")).to_contain_text("テスト 太郎")
pytest.ini でブラウザ・ヘッドレスモードを設定する
# pytest.ini
[pytest]
addopts =
--browser chromium
--headed
--headed はローカル開発・デバッグ用です。GitHub Actions などの CI 環境ではウィンドウを表示できないため、--headless(または addopts から --headed を外す)を使いましょう。CI 用と手元用で設定を分けるか、環境変数で切り替えることを推奨します。# コマンドラインでも指定できる
pytest --browser chromium # Chromium を使う
pytest --browser firefox # Firefox を使う
pytest --headed # ブラウザウィンドウを表示する
pytest --headless # ヘッドレスモード(CI 用)
pytest --slowmo 500 # 操作を500ms遅くしてデバッグしやすくする
⑥ Codegen でテストコードを自動生成する
Codegen はブラウザを操作しながら、その操作を自動でテストコードに変換するツールです。
ロケーターの書き方に迷ったときの出発点として使えます。
# Codegen を起動(URL はテスト対象のページに合わせる)
playwright codegen https://example.com # サンプルURL
ブラウザが開くので操作すると、隣のウィンドウにコードが生成されます。
Codegen はロケーター調査や初期コード作成に便利ですが、そのままコミットすると冗長なコードになりやすいです。生成されたコードを参考にしながら、
data-testid ベースのロケーターに書き直し、テストが増えてきたら fixture 化・POM 化して整理することを推奨します。⑦ スクリーンショットと Trace Viewer
スクリーンショット
# ページ全体のスクリーンショット
page.screenshot(path="screenshots/result.png", full_page=True)
# 特定の要素だけをキャプチャ
page.get_by_test_id("error-message").screenshot(path="screenshots/error.png")
Trace Viewer(テスト失敗の詳細確認)
Trace Viewer はテストの実行過程をステップごとに録画できるツールです。テストが失敗したときに「どの操作でどんな状態だったか」を視覚的に確認できます。
# テスト失敗時に自動でトレースを保存する
pytest --tracing=retain-on-failure
# トレースを開いて確認する
playwright show-trace trace.zip
pytest-playwright を使うと --screenshot=only-on-failure で失敗時のみスクリーンショット保存など、CI 向けの設定が簡単になります。Playwright 入門ではまりやすいポイント 7選
⚠️ よくある落とし穴
- playwright install を忘れている
pip install playwrightだけでは動きません。playwright installでブラウザ本体をダウンロードする必要があります。エラーメッセージに「Executable doesn’t exist」と出たらこれが原因です。 - ヘッドレスモードで動かないのに気づかない
デフォルトはヘッドレス(ウィンドウなし)です。動作確認中は--headedオプションを付けてブラウザを表示すると問題を発見しやすくなります。 - sync と async を混在させている
from playwright.sync_api import sync_playwright(同期)とfrom playwright.async_api import async_playwright(非同期)を混在させるとエラーになります。pytest を使う場合は同期 API が扱いやすいです。 - get_by_role の name に表示テキストが一致しない
get_by_role("button", name="ログイン")はボタンの表示テキストと完全一致または ARIA ラベルで検索します。空白・改行・大文字小文字の違いで見つからないことがあります。Codegen で生成されたコードを参考に確認しましょう。 - with ブロックを閉じ忘れてブラウザが残る
sync_playwright()をwithブロックで使わないとブラウザプロセスが残り続けます。pytest-playwright を使う場合はpagefixture が自動でクリーンアップしてくれます。 - CI で playwright install を実行していない
GitHub Actions などの CI 環境でもplaywright install(またはplaywright install --with-deps)を実行する必要があります。--with-depsを付けるとシステム依存ライブラリも一緒にインストールできます。 - expect のタイムアウトが短すぎる
デフォルトのタイムアウトは通常 5秒(5000ms)ですが、プロジェクト設定で変更できます。CI 環境が遅い場合は10秒以上に延長するケースもあります。expect(locator).to_be_visible(timeout=10000)(ミリ秒)でテストごとに個別設定することも可能です。
よくある質問(FAQ)
Playwright Test は JavaScript/TypeScript 向けの Playwright 専用テストランナーで、@playwright/test パッケージとして提供されています。pytest-playwright は Python の pytest フレームワーク向けの Playwright プラグインです。Python でテスト自動化する場合は pytest-playwright を使います。機能面では Playwright Test の方が Playwright との統合が深い部分もありますが、Python エコシステムで統一したい場合は pytest-playwright で十分です。
既存の Selenium テストが安定して動いているなら、無理に移行する必要はありません。ただし新規のテストを追加する場合は Playwright を選ぶ価値は十分あります。自動待機・Codegen・Trace Viewer が標準搭載されており、Flaky Test が減りやすい設計です。実務では Selenium を既存資産として残しつつ、新規フローから Playwright で書き始めるケースもよく見られます。
はい、Python だけで使えます。 Playwright の Python API は Python 標準の書き方で動作するため、JavaScript の知識は不要です。ただし、テスト対象の Web アプリが JavaScript で作られている場合、JavaScript の基本概念(DOM・非同期処理など)を知っておくと、テストの設計やデバッグがしやすくなります。
はい、完全無料のオープンソースです。Microsoft が開発・メンテナンスしており、MIT ライセンスで公開されています。商用プロジェクトでも無料で利用できます。
Python を使うなら Playwright 一択です。 Cypress は JavaScript/TypeScript 専用のため、Python テストには使えません。JavaScript も使える場合は、Playwright の方がマルチブラウザ対応・マルチ言語対応で柔軟性が高く、iFrame・新規タブ・認証フローなど複雑な操作にも対応しやすいです。
はい。Playwright は Python・JavaScript/TypeScript・Java・C# に対応しています。QA エンジニアが Python を選ぶのは、pytest との親和性の高さと、Selenium で培ったノウハウを活かしやすいためです。
必須ではありません。sync_playwright() を使えば pytest なしでも、あるいは pytest.fixture で自分で管理することもできます。ただし pytest-playwright を使うと page・browser・context の fixture が自動で使えて、ブラウザのセットアップ・クリーンアップが省略できるため、実務では使うことを推奨します。
pytest --browser chromium --browser firefox のように複数指定できます。CI では主要ブラウザをまとめて実行できます。ただしすべてのブラウザで実行するとテスト時間が倍以上になるため、まずは Chromium に絞って安定させてから追加するのがおすすめです。
Web 要素の状態確認には Playwright の expect を使いましょう。 expect は内部でリトライを繰り返し、条件が満たされるまで待ちます。Python の assert は一瞬で評価されるため、非同期で変化するページ状態の確認に使うと Flaky Test になりがちです。
デフォルトでは load イベント(DOM と一部のリソース読み込み完了)まで待ちます。SPA(シングルページアプリケーション)など JavaScript で描画されるページでは、page.goto() 後に要素の表示完了を待つ必要があります。wait_until="networkidle" が有効なケースもありますが、Playwright 公式では過信は推奨されておらず、まずは expect()・page.wait_for_url()・locator.wait_for() を使った待機を優先することを推奨します。 WebSocket など永続通信を持つ SPA では networkidle が安定しない場合があります。
基本的には不要です。 Playwright の操作(click()・fill())は要素が操作可能になるまで自動で待機します。どうしても待機が必要な場合は page.wait_for_selector()・page.wait_for_url()・expect を使いましょう。
まとめ
| ステップ | やること |
|---|---|
| ① インストール | pip install playwright pytest-playwright → playwright install |
| ② 動作確認 | sync_playwright() でページを開いてスクリーンショットを撮る |
| ③ pytest テスト | page fixture を使って get_by_role・fill・click・expect |
| ④ 整理 | conftest.py に共通処理を集約。pytest.ini でブラウザ設定 |
| ⑤ デバッグ | Codegen でロケーター確認、--tracing=retain-on-failure で失敗を可視化 |
Playwright は自動待機・Trace Viewer・Codegen が標準搭載されており、Selenium より設定が少なく、初めてブラウザ自動化を学ぶ方にも取り組みやすいツールです。
まず playwright codegen でどんなコードが生成されるか試してみるだけでも、全体像が把握できます。
次のステップとして、テストが増えてきたら Page Object Model(POM) でコードを整理するか、GitHub Actions で CI に組み込む方法に進みましょう。
