Playwrightとは
Playwrightはマイクロソフトが2020年初頭にリリースした次世代の自動化テストツールです。現在最も広く使われているSeleniumと比較すると、Chromium、Firefox、WebKitなどの主要ブラウザを自動化するためのAPIが1つだけで済む点が特徴です。Python言語向けの純粋な自動化ツールとして、回帰テストにおける自動化実装をより迅速に行うことができます。
Playwrightを選ぶ理由
- Playwrightの利点
- SeleniumはWebDriverを介してブラウザを操作する必要がありますが、Playwrightは開発者ツールを通じてブラウザと直接やり取りするため、ドライバのインストールが不要でセットアップが簡単です。
- Playwrightはほぼすべての言語をサポートし、様々なドライバに依存せず、組み込みブラウザを呼び出すため起動速度が速いです。
- SeleniumはHTTPプロトコル(一方向通信)に基づいていますが、PlaywrightはWebSocket(双方向通信)を使用し、ブラウザの実際の状況を自動的に取得できます。
- Playwrightは自動待機機能を備えています。
- 既知の制限
- Playwrightは旧版Microsoft EdgeやIE11をサポートしていません。新しいMicrosoft Edge(Chromiumベース)のみをサポートするため、ブラウザバージョンに厳しい要件があるプロジェクトには適していません。
- SSL証明書が必要なサイトへのアクセスは録画できない場合があり、このプロセスは個別に位置特定してコーディングする必要があります。
- モバイル端末テストはデスクトップブラウザを使用してモバイルデバイスをシミュレートする(実質的に内蔵エミュレータ)ため、実機を制御することはできません。
Playwrightの使用方法
インストール
PlaywrightはAsync/Await構文をサポートしているため、Python 3.7以上が必要です。
pip install playwright
Chromium、Firefox、WebKitなどのブラウザのドライバファイル(組み込みブラウザ)をインストールします。
python -m playwright install
自動録画
コマンドラインで--helpを入力すると、すべてのオプションを確認できます。
python -m playwright codegen --help
開始ページをhttps://baidu.com/として録画を開始します。
python -m playwright codegen https://baidu.com/
https://baidu.com/を開き、Chromiumドライバを使用して結果をmy.pyというPythonファイルに保存します。
python -m playwright codegen --target python -o 'my.py' -b chromium https://baidu.com/
-target:生成するスクリプトの言語を指定(JSとPythonの2種類、デフォルトはPython)
-b:ブラウザドライバを指定
-o:録画したスクリプトをファイルに保存
カスタムコードの作成
要素の定位
単一要素の選択:querySelector(engine=body)
複数要素の選択:querySelectorAll(engine=body)
単一要素を選択し、自動待機:waitForSelector(engine=body)
Byの8種類の定位方法は実際には4種類
id、name、tag name、class name(JavaとPythonはこの4種類をすべてCSSに分類)
xpath、link text、partial link text、css selector
W3C標準で規定されたwebDriverプロトコルは5種類の定位方法
CSS、Link text、Partial link text、Tag name、XPath
Playwrightはセレクタを3種類にまとめています
CSS、XPATH(論理式と関数をサポート)、TEXT
セレクタのルール
CSS:IDセレクタ、クラスセレクタ、要素セレクタ、属性セレクタ、ワイルドカードセレクタ、階層セレクタ。
XPath:XMLパス言語であり、XMLドキュメントを「パス識別子」を通じてナビゲートします。HTMLのようなXML形式でも使用できます。
Text:構造化コンテンツ(html、xml、json)には曖昧一致(大文字小文字を無視、前後の空白を無視、部分文字列を検索)および正確一致、非構造化コンテンツには正規表現一致を使用します。
要素の一般的な操作
ドロップダウン選択ボックス:selectOption、value、labei、index
ファイルアップロード:setInputFiles、単一ファイル、複数ファイル、ドラッグ&ドロップアップロード
マウスクリック:click、dbclick
マウスドラッグ:down、up
マウス移動:move
タッチスクリーン:tag
キーボードキー:press
スクリーンショット、録画:screenshot、recordVideo
ネットワークインターセプト(モックインターフェース)
page = context.newPage()
def should_intercept(request) -> bool:
return True # インターセプトを実行
# return False # インターセプトを実行しない
async def handle_route(route):
print(route.request.url)
# 通常のアクセス
# await route.continue_()
# アクセスを拒否
# await route.abort("ネットワークインターセプト")
# 別のアドレスにリダイレクト
await route.fulfill(
status=302,
headers={
'Location': "https://baidu.com/"
}
)
page.route(should_intercept, handle_route)
同期実行
# 3つのブラウザを順番に開き、行者公式サイトにアクセスし、スクリーンショットを撮影して終了します。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
for browser_type in [p.chromium, p.firefox, p.webkit]:
# ヘッドレスモードを指定(Trueはヘッドレスモード)
browser = browser_type.launch(headless=False)
page = browser.new_page()
page.goto('https://baidu.com/')
# ページが完全に読み込まれるのを待ってスクリーンショットを撮影
page.wait_for_selector("text=インテリジェントコンテンツレビュー")
page.screenshot(path=f'example-{browser_type.name}.png')
browser.close()
非同期実行
# 3つのブラウザ操作を同時に行う
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
for browser_type in [p.chromium, p.firefox, p.webkit]:
browser = await browser_type.launch()
page = await browser.new_page()
await page.goto('https://baidu.com/')
await page.wait_for_selector("text=インテリジェントコンテンツレビュー")
await page.screenshot(path=f'example-{browser_type.name}.png')
await browser.close()
asyncio.run(main())
Pytestとの統合
インストール:pip install pytest-playwright
def test_playwright(page):
page.goto("https://baidu.com/")
with page.expect_popup() as popup_info:
page.click('text="インテリジェントコンテンツレビュー"')
assert "インテリジェントコンテンツレビュー" == element.text_content()
モバイル端末操作
現在サポートされているシミュレーションデバイスは比較的少ないです。参照:デバイスリスト
from time import sleep
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
galaxy_s5 = p.devices['Galaxy S5']
browser = p.chromium.launch(headless=False)
context = browser.new_context(**galaxy_s5)
page = context.new_page()
page.goto('https://baidu.com/')
page.click('text="インテリジェントコンテンツレビュー"')
# スクリーンショット
# page.screenshot(path='colosseum-GalaxyS5.png')
sleep(10)
browser.close()