WebView2
はじめに
以下では、Playwright を Microsoft Edge WebView2 で使用する方法について説明します。WebView2 は WinForms コントロールであり、内部的には Microsoft Edge を使用して Web コンテンツをレンダリングします。これは Microsoft Edge ブラウザの一部であり、Windows 10 および Windows 11 で利用できます。Playwright は WebView2 アプリケーションを自動化するために使用でき、WebView2 で Web コンテンツをテストするために使用できます。WebView2 に接続するために、Playwright は browser_type.connect_over_cdp() を使用します。これは Chrome DevTools Protocol (CDP) 経由で接続します。
概要
WebView2 コントロールは、WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS
環境変数を --remote-debugging-port=9222
で設定するか、EnsureCoreWebView2Async を --remote-debugging-port=9222
引数で呼び出すことで、受信 CDP 接続をリッスンするように指示できます。これにより、Chrome DevTools Protocol が有効になった状態で WebView2 プロセスが開始され、Playwright による自動化が可能になります。9222 はこの場合のポートの例ですが、他の未使用ポートも同様に使用できます。
await this.webView.EnsureCoreWebView2Async(await CoreWebView2Environment.CreateAsync(null, null, new CoreWebView2EnvironmentOptions()
{
AdditionalBrowserArguments = "--remote-debugging-port=9222",
})).ConfigureAwait(false);
WebView2 コントロールを備えたアプリケーションが実行されたら、Playwright 経由で接続できます。
- 同期
- 非同期
browser = playwright.chromium.connect_over_cdp("http://localhost:9222")
context = browser.contexts[0]
page = context.pages[0]
browser = await playwright.chromium.connect_over_cdp("http://localhost:9222")
context = browser.contexts[0]
page = context.pages[0]
WebView2 コントロールの準備が整っていることを確認するために、CoreWebView2InitializationCompleted
イベントを待つことができます。
this.webView.CoreWebView2InitializationCompleted += (_, e) =>
{
if (e.IsSuccess)
{
Console.WriteLine("WebView2 initialized");
}
};
テストの作成と実行
デフォルトでは、WebView2 コントロールはすべてのインスタンスで同じユーザーデータディレクトリを使用します。これは、複数のテストを並行して実行すると、互いに干渉することを意味します。これを避けるために、WEBVIEW2_USER_DATA_FOLDER
環境変数を設定するか(または WebView2.EnsureCoreWebView2Async メソッド を使用)、各テストで異なるフォルダーに設定する必要があります。これにより、各テストが独自のユーザーデータディレクトリで実行されるようになります。
以下を使用すると、Playwright は WebView2 アプリケーションをサブプロセスとして実行し、一意のユーザーデータディレクトリを割り当て、テストに Page インスタンスを提供します。
import os
import socket
import tempfile
import pytest
from pathlib import Path
from playwright.sync_api import Playwright, Browser, BrowserContext
import subprocess
EXECUTABLE_PATH = (
Path(__file__).parent
/ ".."
/ "webview2-app"
/ "bin"
/ "Debug"
/ "net8.0-windows"
/ "webview2.exe"
)
@pytest.fixture(scope="session")
def data_dir():
with tempfile.TemporaryDirectory(
prefix="playwright-webview2-tests", ignore_cleanup_errors=True
) as tmpdirname:
yield tmpdirname
@pytest.fixture(scope="session")
def webview2_process_cdp_port(data_dir: str):
cdp_port = _find_free_port()
process = subprocess.Popen(
[EXECUTABLE_PATH],
env={
**dict(os.environ),
"WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS": f"--remote-debugging-port={cdp_port}",
"WEBVIEW2_USER_DATA_FOLDER": data_dir,
},
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
)
while True:
line = process.stdout.readline()
if "WebView2 initialized" in line:
break
yield cdp_port
process.terminate()
@pytest.fixture(scope="session")
def browser(playwright: Playwright, webview2_process_cdp_port: int):
browser = playwright.chromium.connect_over_cdp(
f"http://127.0.0.1:{webview2_process_cdp_port}"
)
yield browser
@pytest.fixture(scope="function")
def context(browser: Browser):
context = browser.contexts[0]
yield context
@pytest.fixture(scope="function")
def page(context: BrowserContext):
page = context.pages[0]
yield page
def _find_free_port(port=9000, max_port=65535):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while port <= max_port:
try:
sock.bind(("", port))
sock.close()
return port
except OSError:
port += 1
raise IOError("no free ports")
from playwright.sync_api import Page, expect
def test_webview2(page: Page):
page.goto("https://playwright.dokyumento.jp")
get_started = page.get_by_text("Get Started")
expect(get_started).to_be_visible()
デバッグ
webview2 コントロール内で、右クリックしてコンテキストメニューを開き、「Inspect」を選択して DevTools を開くか、F12 キーを押すだけです。WebView2.CoreWebView2.OpenDevToolsWindow メソッドを使用して、プログラムで DevTools を開くこともできます。
テストのデバッグについては、Playwright デバッグガイド を参照してください。