6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

BlazorAdvent Calendar 2022

Day 12

[助けを求む] Blazor Server を Playwright で E2E テストするとき、Playwright の初動が早すぎてテストが失敗する

Posted at

Playwright で Blazor Server の E2E テストを書いたらテスト失敗するようになってしまった!

Blazor アプリケーションのエンド・ツー・エンド (End-to-End, 略して E2E) テストを実装する際、ここ最近は Selenium ではなく、Playwright (の .NET バインディング) を使って Web ブラウザの自動操作を実装しています。

先日も、とある手持ちの Blazro Server アプリケーションの E2E テストを、Seleinum を使って実装していたところを、Paywright を使った実装に置き換えたりしていました。

すると、その Playwright を使うように変更した Blazor Server アプリケーションの E2E テストが失敗するようになったのです。

例えば、Blazor プログラマであればお馴染みであろう (?)、例の「カウンター」ページの E2E テストを実装しているとしましょう。この「カウンター」ページの「Click me」ボタンをクリックしたら、カウンターの数字が 0 から 1 になっていることをテストする、とします。
image.png
Selenium で実装していたころはこのテストはもちろん成功していました。しかし、Playwright に置き換えて以降、このテストが失敗するようになってしまいました。失敗の原因は、カウンターの数字が 0 のままで、1 に加算されない、というものです。「Click me」ボタンが見つからないとかそういう原因ではないのです。一体何が起きているのでしょうか。

もしかして... Playwright が早すぎる!?

いろいろ探っていくうちに、どうやら、次のような動作になっているのではないかと推測されるに至りました。

  • (既定の実装だと) Blazor Server はサーバー側でプリレンダリングされる
  • Playwright で自動操縦されている Web ブラウザが、このプリレンダリングされたコンテンツを読み込んで表示する
  • ただし、プリレンダリングされたコンテンツを読み込んで表示した直後は、サーバー側との SignalR 接続が確立され、かつ、すべてのイベントハンドラが配線される前のタイミングが存在する!
  • Playwright の動作が高速であることによって、この Blazor Server 起動時の絶妙なタイミングで、Playwright が (プリレンダリングされた)「Click me」ボタンをクリックしてしまう?
  • しかし、「Click me」ボタンは (プリレンダリングされているので) たしかに存在するものの、イベントハンドラは配線前なので、ボタンクリックに対するカウンター加算は起動されない。結果、「Click me」ボタンをクリックしてもカウンターは 0 のまま!

上記仮説が正しいとして、サーバー側プリレンダリングを止めると、このようなことは起きなくなるのかもしれません。しかし、せっかくのサーバー側プリレンダリングはこのまま維持したいため、プリレンダリングを止めるという選択は避けたいです。どうしたらよいでしょうか。

とりあえずの回避策を実装したものの...

今のところは、Blazor Server アプリケーション側に以下の "仕込み" を入れて、この E2E テストの失敗を回避するようにしました。

  • console.log を呼び出せる JavaScript ヘルパ関数を用意
  • Blazor Server の MainLayout.razor にて、OnAfterRenderAsync のタイミングIJSRuntime.InVokeAsync を使って上記 JavaScript ヘルパ関数を呼び出し、"The Blazor Server app has been started." というテキストを console.log で出力
  • Playwright による E2E テスト実装側では、ページナビゲーション後、その console.log 出力を WaitForConsoleMessage で待機してから、続くボタンクリックなどのテストを実行する

Blazor Server 側で Razor コンポーネントのライフサイクルメソッド OnAfterRenderAsync が呼び出されるタイミングは、ブラウザ側との接続も確立され、初回のレンダリングが完了した後になりますから、Playwright による E2E テストもこのタイミングに歩調を合わせることで、テストが安定化したと考えられます。

もっとマシなやり方があれば教えてもらえると嬉しいです!

...ということで、どうにかこの「Playwright の初動が早すぎてテストが失敗する」問題をねじ伏せたものの、本来であれば無用な console.log 出力があるのが納得いきません。Blazor Server 側にこのような "実装" "改造" が必要なのも、汎用性がなくイヤです。E2E テスト実装側でページナビゲーション後に数百ミリ秒の待機を差し込むことでも改善できるかもしれませんが、これまた、そのような微妙なマジックナンバーの待機を挟むのも、もうこりごりです。

何か他に上手い方策はないでしょうか、もっとマシなやり方があれば教えてもらえると嬉しいです!

6
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?