はじめに
Vue.js + .NET の CSR アプリケーションに E2E テストとして Playwright を導入した際にエラーが発生し、ローカル環境で実行している対象アプリケーションに対してテストを実行できませんでした。
本投稿では以下のエラー解消のために実施した切り分けの過程と対処方法をまとめます。
-
テストを実行してもエラーが出ずに止まる
- 原因はプロキシの環境変数で、
NO_PROXYに localhost を追加して対処
- 原因はプロキシの環境変数で、
-
webServerで .NET アプリを起動するとself-signed certificateエラーになる- 原因は .NET の開発用の自己署名証明書で、
webServer.ignoreHTTPSErrorsで対処
- 原因は .NET の開発用の自己署名証明書で、
環境
- OS : Windows 11
- Node.js : 24.13.0
- Playwright(@playwright/test) : 1.62.1
- Vue : 3.5.30
- .NET 10
Playwright 導入先のアプリケーションは AlesInfiny Maris v2.1.2 時点のサンプルアプリ Dressca です。
テスト対象アプリの構成
| URL | ミドルウェア | |
|---|---|---|
| フロントエンド (Vue.js) | http://localhost:5173 |
Vite の開発サーバー |
| バックエンド (.NET) | https://localhost:5001 |
Kestrel (.NET の既定のサーバー) |
Playwright の導入手順
Playwright の導入は 公式のインストール手順 に従い、以下のコマンドで行いました。
npm init playwright@latest
インストール完了直後は必要となる依存関係と、 tests フォルダー、 playwright.config.ts が追加されます。
Dressca
├ dressca-frontend (フロントエンドの Vue.js アプリ)
│ └ consumer (ワークスペース名)
│ ├ tests/
│ │ └ example.spec.ts ------- E2E テストのサンプルコード
│ ├ package.json ------------ ワークスペースのメタデータ、依存関係、スクリプトなどを定義するファイル
│ ├ playwright.config.ts ---- Playwright の設定ファイル
│ └ vite.config.ts ---------- Vite の設定ファイル
└ dressca-backend (バックエンドの .NET アプリ)
example.spec.ts には Playwright の公式サイトにアクセスするテストコードがサンプルとして追加されています。
import { test, expect } from '@playwright/test'
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
この時点では以下のコマンドを実行して、テストが通ることを確認できました。
※デフォルトでは 3 つのブラウザでテストが実行されるため、 3 件成功と表示されます。
> npx playwright test
Running 3 tests using 3 workers
3 passed (29.3s)
To open last HTML report run:
npx playwright show-report
開発環境用に Playwright の設定をカスタマイズする
サンプルアプリの E2E テストを実施するため、以下の変更を行いました。
1. 設定ファイル playwright.config.ts の修正
テスト実行時のブラウザの指定と、テスト実行対象のフロントエンド・バックエンドアプリを起動するための設定を主に行っています。
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
use: {
trace: 'on-first-retry',
},
/* テスト実行時の構成。(Chromium のみでテスト実行)*/
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
- {
- name: 'firefox',
- use: { ...devices['Desktop Firefox'] },
- },
- {
- name: 'webkit',
- use: { ...devices['Desktop Safari'] },
- },
],
/* テスト実行前にローカル開発サーバーを起動する。 */
+ webServer: [
+ {
+ command: 'npm run dev',
+ url: 'http://localhost:5173',
+ reuseExistingServer: !process.env.CI,
+ timeout: 60 * 1000,
+ },
+ {
+ command: 'dotnet run',
+ cwd: '../../dressca-backend/src/Dressca.Web.Consumer',
+ url: 'https://localhost:5001',
+ reuseExistingServer: !process.env.CI,
+ timeout: 120 * 1000,
+ },
+ ],
});
playwright.config.ts の設定値については公式ドキュメントを参照してください。
2. テストコードの修正
サンプルアプリ上のページにアクセスするよう example.spec.ts のテストコードを修正しました。
import { test, expect } from '@playwright/test'
test('サンプルアプリにアクセス', async ({ page }) => {
await page.goto('http://localhost:5173/')
await expect(page).toHaveTitle(/Dressca/)
})
エラー① npx playwright test 実行時に何も出力されず固まる
症状
「開発環境用に Playwright の設定をカスタマイズする」の実施直後に npx playwright test を実行すると、数分待ってもテストが実行されませんでした。
以下のようにエラーも特に出力されず、単に止まっているように見えます。
> npx playwright test
エラー原因の切り分け
timeout を伸ばす
テスト実行時にアプリケーションを起動しているため、起動に長時間かかっていると考え、timeout の設定を伸ばした状態で再実行しました。
webServer: [
{
command: 'npm run dev',
url: 'http://localhost:5173',
reuseExistingServer: !process.env.CI,
- timeout: 60 * 1000,
+ timeout: 180 * 1000, // 3分まで伸ばしてみる
},
{
command: 'dotnet run',
cwd: '../../dressca-backend/src/Dressca.Web.Consumer',
url: 'https://localhost:5001',
reuseExistingServer: !process.env.CI,
- timeout: 120 * 1000,
+ timeout: 300 * 1000, // 5分まで伸ばしてみる
},
],
timeout に設定した時間が経過した後もテストが実行されている様子はなく、出力内容に変化はありませんでした。
バックエンドの起動設定を削除する
バックエンドアプリの方が起動時間に時間がかかる傾向にあったため、 webServer からバックエンド側の起動設定を削除の上テストを実行しましたが、何も出力されないままでした。
アプリケーションを手動で起動する
webServer.reuseExistingServer が true の場合、 url に設定したサーバーが起動済みであれば command を実行せずにそのサーバーを利用します。
アプリケーションが起動している状態でテスト実行可能か確認するため、
webServer.reuseExistingServer を明示的に true に設定し、手動でフロントエンド・バックエンドアプリを起動しました。ブラウザから正常動作していることを確認した上でテストを実行しましたが、何も出力されないままでした。
アプリを手動で起動しても結果が変わらなかったことから、アプリの起動自体には問題がないと考えられます。
デバッグログの出力
ドキュメント を参考に、環境変数 DEBUG=pw:webserver を設定の上テストを実行し、デバッグログを出力するようにしました。
サーバーへの GET リクエストが送信されていることは確認できましたが、その後はタイムアウトの時間を過ぎても出力がありませんでした。
> $env:DEBUG="pw:webserver"
> npx playwright test
pw:webserver HTTP GET: http://localhost:5173/ +0ms
これらの結果と設定のカスタマイズ前に Playwright 公式サイトへアクセスするテストが正常に実行できていたことから、localhost へのアクセスに異常があると分かりました。
原因
筆者のローカル環境では環境変数 HTTP_PROXY / HTTPS_PROXY を設定していたため、 Playwright 実行時にプロキシ経由で localhost へアクセスを試みて失敗していたことが原因でした。HTTP_PROXY, HTTPS_PROXY の設定を削除するとテストが実行できました。
プロキシからは開発マシンの localhost に到達できないため、応答が返らず待ち続けていたと考えられます。
-
HTTP_PROXY,HTTPS_PROXY設定時- プロキシ経由でリクエストを送ると、localhost の名前解決はプロキシサーバー側で行われます。プロキシサーバーにとっての localhost は、プロキシサーバー自身(開発マシンではない)を指すため、テスト対象アプリにリクエストが届きません。
-
HTTP_PROXY,HTTPS_PROXY未設定- プロキシサーバーを経由しないため、開発マシン上の localhost に接続し、テスト対象アプリが応答を返します。
対処
localhost へのアクセス失敗に関して調査を続けたところ、環境変数 NO_PROXY に localhost を追加することで解消できる場合があると分かりました。
NO_PROXY は、プロキシを経由せずに直接接続する宛先を指定する環境変数です。
以下のように NO_PROXY に localhost を追加してから npx playwright test を実行することで、テストの実行が確認できました。
$env:NO_PROXY = "localhost,127.0.0.1"
補足: 環境変数設定の共通化
E2E テスト実行の度に環境変数を設定するのは煩雑であり、他の開発者のローカル環境でも同様に実行できるようにする必要がありました。そのため、以下のように playwright.config.ts に実装を追加して対処することとしました。
import { defineConfig, devices } from '@playwright/test'
+ process.env.NO_PROXY = process.env.NO_PROXY
+ ? `${process.env.NO_PROXY},localhost,127.0.0.1`
+ : 'localhost,127.0.0.1'
export default defineConfig({
// ...
})
プロキシ関連の環境変数には大文字 (NO_PROXY) と小文字(no_proxy) の2通りの書き方があり、ツールによってどちらを参照するかが異なる場合があります。
Windows では環境変数の大文字小文字を区別しないため NO_PROXY で動作しますが、Linux では no_proxy の設定が必要となる場合があります。
エラー② self-signed certificate エラーになる
症状
エラー①の対処後、次のエラーになりました。
Error while checking if https://localhost:5001/ is available: self-signed certificate;
if the root CA is installed locally, try running Node.js with --use-system-ca
エラー原因の切り分け
エラーメッセージの案内どおり NODE_OPTIONS=--use-system-ca と NODE_USE_SYSTEM_CA=1 を試しましたが、同じエラーになりました。Node.js 単体で --use-system-ca を付けて接続しても同じエラーになったため Playwright 固有の問題ではなさそうです。
原因
エラーメッセージのとおり、webServer の起動確認で証明書の検証に失敗していました。
.NET の開発用 HTTPS 証明書は自己署名証明書で、Node.js がこの証明書を信頼していませんでした。
--use-system-ca を指定しても解消しなかったのは、自己署名証明書が OS の「信頼されたルート証明機関」に登録されていなかったためと考えられます。
対処
Playwright の設定で webServer の ignoreHTTPSErrors: true を指定することで解消しました。
webServer: [
// ...
{
command: 'dotnet run',
cwd: '../../dressca-backend/src/Dressca.Web.Consumer',
url: 'https://localhost:5001',
+ ignoreHTTPSErrors: true, // 起動確認時のHTTPSエラーを無視
reuseExistingServer: !process.env.CI,
},
],
ignoreHTTPSErrors の設定以外にも、テスト実行時のみ HTTP ポートでバックエンドアプリに接続する方法もありましたが、アプリケーション実行時とできるだけ近い構成でテストを実行するため ignoreHTTPSErrors: true を設定することで恒久対応としました。
ignoreHTTPSErrors: true を設定するデメリット
本設定により、webServer の起動確認のリクエスト(url へのアクセス)で証明書の検証を行わなくなるため、接続先が意図したサーバーかを検証しなくなります。
webServer は、テスト時に開発マシン上のサーバーを起動する機能で、今回の url も localhost です。また、起動確認ではサーバーが応答するかどうかを調べるだけで、機密情報を送受信しません。そのため、この設定による実質的なリスクは小さいと考えています。
use.ignoreHTTPSErrors との違い
playwright.config.ts では ignoreHTTPSErrors を指定する箇所が複数あります。
| 場所 | 効果の対象 |
|---|---|
webServer.ignoreHTTPSErrors |
webServer の起動確認リクエスト |
use.ignoreHTTPSErrors |
テスト中にブラウザが行うアクセス |
今回のエラーは起動確認で出ていたため、webServer 側の設定を行いました。
また、テスト中は Playwright からバックエンドアプリに直接アクセスしないため、 use 側の設定は行っていません。テストコードからバックエンドの HTTPS の URL に直接アクセスする場合は、 use 側にも指定します。
まとめ
Playwright のインストール自体は非常に簡単にできましたが、環境やアプリケーションの設定との兼ね合いで導入時のデバッグに時間を費やしてしまいました。
Playwright 導入時にテストが動かない、あるいは起動確認で失敗する場合は、次を確認してみてください。
-
HTTP_PROXY/HTTPS_PROXYを設定していないか
⇒NO_PROXYにlocalhost,127.0.0.1を追加 -
webServerで HTTPS の URL を指定していないか
⇒自己署名証明書ならwebServer.ignoreHTTPSErrors: true
似たような課題を抱えている方の参考になれば幸いです。
BIPROGYグループの技術への取り組み
We Are Hiring!