【.NET】Playwright初回時のPlaywrightException対応

# はじめに
Webアプリケーションのテスト自動化を目指して、Selenium よりは Playwright にしようと思っています。 

https://zenn.dev/coconala/articles/40849ff2533f84

https://programabl.com/ja/i-switched-e2e-test-to-playwright/

# Playwright とは
Playwrightは、Microsoftが中心になって開発しているブラウザを操作するためのライブラリとなります。E2E（エンドツーエンドテスト）テストツールです。｢脚本家｣という意味があります。

Chrome系のブラウザには、外部から操作・通信するためのプロトコルが実装されています。Playwrightはそのプロトコルを使ってブラウザを直接操作します。

## Seleniumとの違い  
Seleniumは、WebDriverを使ってブラウザを操作します。その為、Chromeのバージョンアップにともなって適合するバージョンのドライバーをダウンロードする必要があります。
Playwrightにはドライバーが含まれています、その代わりWebDriverより対応するブラウザの対応種類が少ないです。

Seleniumでは要素が表示されるのを待つために待機時間を指定していたのですが、Playwrightでは待機時間を指定しなくても要素が操作可能になるのを自動的に待機する機能が備わっています。

# 環境
* Windows 11 Home
* .NET 7.0

# 例外エラー
下記サイトを参考に NuGet で「Microsoft Playwright」をインストール、Winフォームにボタンを追加してプログラムをコピペして実行すると例外エラーが出ました。

https://web.biz-prog.net/playwright/install_cs.html

```
Microsoft.Playwright.PlaywrightException: 'Executable doesn't exist at %LOCALAPPDATA%\ms-playwright\chromium-1067\chrome-win\chrome.exe
╔════════════════════════════════════════════════════════════╗
║ Looks like Playwright was just installed or updated.       ║
║ Please run the following command to download new browsers: ║
║                                                            ║
║      pwsh bin\Debug\netX\playwright.ps1 install            ║
║                                                            ║
║ <3 Playwright Team                                         ║
╚════════════════════════════════════════════════════════════╝
```

# 対応
メッセージを見ると、「playwright.ps1 install」を実行するように求められています。

```
pwsh bin\Debug\netX\playwright.ps1 install
```
* netXの部分は、今回はWindowsの.NET 7.0で作成したので、`net7.0-windows`になります。
* pwshは、PowerShellのことです。
* playwright.ps1ファイルは、`bin\Debug\net7.0-windows`フォルダに自動生成されています。

## スクリプト実行ポリシーの変更
Windows Terminal画面を開くと PowerShellが起動します。
自分の場合、セキュリティエラーが出たので管理者権限で Windows Terminal画面を開き直して、`Set-ExecutionPolicy RemoteSigned`を先に実行しました。

```
PS > Set-ExecutionPolicy RemoteSigned
```

:::note warn
Set-ExecutionPolicy RemoteSignedは、実行ポリシーを恒久的に変更します。
この操作はシステム全体に影響を与えるため、管理者権限が必要となります。
:::

## PowerShellスクリプト実行
今回 WinPlaywrightプロジェクト名で Winフォームアプリケーションを作成しました。プロジェクト名のところは各自に置き換えて下さい。

:::note
PowerShellではスクリプト・ファイルを実行する場合に必ず絶対パスか相対パス形式でファイルを指定しなければならないので、相対パスの「./」を付けて実行します。
:::

```
PS > CD C:\WorkSpace\WinPlaywright\bin\Debug\net7.0-windows
PS C:\WorkSpace\WinPlaywright\bin\Debug\net7.0-windows> ./playwright install
```

ダウンロードが始まります。

```
Downloading Chromium 115.0.5790.24 (playwright build v1067) from https://playwright.azureedge.net/builds/chromium/1067/chromium-win64.zip
114.3 Mb [====================] 100% 0.0s
Chromium 115.0.5790.24 (playwright build v1067) downloaded to C:\Users\yaju\AppData\Local\ms-playwright\chromium-1067
Downloading FFMPEG playwright build v1009 from https://playwright.azureedge.net/builds/ffmpeg/1009/ffmpeg-win64.zip
1.4 Mb [====================] 100% 0.0s
FFMPEG playwright build v1009 downloaded to C:\Users\yaju\AppData\Local\ms-playwright\ffmpeg-1009
Downloading Firefox 113.0 (playwright build v1408) from https://playwright.azureedge.net/builds/firefox/1408/firefox-win64.zip
79.7 Mb [====================] 100% 0.0s
Firefox 113.0 (playwright build v1408) downloaded to C:\Users\yaju\AppData\Local\ms-playwright\firefox-1408
Downloading Webkit 16.4 (playwright build v1860) from https://playwright.azureedge.net/builds/webkit/1860/webkit-win64.zip
45.5 Mb [====================] 100% 0.0s
Webkit 16.4 (playwright build v1860) downloaded to
```

# コマンドプロンプトによる対応
別PCで上記と同じことをやりました。

今回のPCでは PowerShellの恒久的な実行ポリシーの変更はしないで、ExecutionPolicy オプションによる実行ポリシーの変更をしています。

```
cd C:\WorkSpace\WinFormsApp1\WinFormsApp1\bin\Debug\net7.0-windows
PowerShell -ExecutionPolicy RemoteSigned .\playwright.ps1 install
```

上記と同じように、ダウンロードが始まります。

# Playwrightを組み込んだアプリの配布
https://www.meziantou.net/distributing-applications-that-depend-on-microsoft-playwright.htm

`playwright.ps1` がどういった仕組みだったのかというと、中身を見るとわかりますが、`Microsoft.Playwright.dll` を参照して、Mainメソッドを呼んでるだけでした。

## playwright.ps1の中身
```powershell:playwright.ps1
#!/usr/bin/env pwsh

$PlaywrightFileName = Join-Path $PSScriptRoot "Microsoft.Playwright.dll"
[Reflection.Assembly]::LoadFile($PlaywrightFileName) | Out-Null
exit [Microsoft.Playwright.Program]::Main($args)
```

## C#の場合
`playwright.ps1` の中身をC#に展開したのが、下記になるということです。
配布用には`Microsoft.Playwright.dll`が必要になることと、Playwright用ドライバーが未インストールの初回だけダウンロード用にインターネット接続が必要になります。その後は社内LANのみで実行できます。

```cs
using Microsoft.Playwright;

Console.WriteLine("Installing browsers");

// The following line installs the default browsers. If you only need a subset of browsers,
// you can specify the list of browsers you want to install among: chromium, chrome,
// chrome-beta, msedge, msedge-beta, msedge-dev, firefox, and webkit.
// var exitCode = Microsoft.Playwright.Program.Main(new[] { "install", "webkit", "chrome" });
// If you need to install dependencies, you can add "--with-deps"
var exitCode = Microsoft.Playwright.Program.Main(new[] { "install" });
if (exitCode != 0)
{
    Console.WriteLine("Failed to install browsers");
    Environment.Exit(exitCode);
}

Console.WriteLine("Browsers installed");
```

# 最後に
これでようやくボタンクリックで例外エラーなく、ブラウザーが起動することが出来ました。