マンガ読んだ!!にシステムテストを導入したくて、モブプロでアドバイスを頼んだ話

マンガ読んだ!!にシステムテストを導入したい

マンガ読んだ!!というサービスを作っています。マンガ読んだ!!は残念ながら現在殆どテストを書いていません。そのため以前から思いもよらないページが落ちていることが何度もありました。だからシステムテストを導入したいという気持ちはありました。Webのシステムテストに関して、Seleniumを使ったテストを書けば良いことは分かっていましたが、マンガ読んだ!!はSPAなのでテストの書き方にもコツがいりそうです。また僕個人がWebの実務経験がないので、htmlのタグの勘所も良くわかっていません。他人のアドバイスを借りないとスタートでかなり時間を取られそうと思ったためアドバイスをもらうことにしました。今回は実験的にモブプロ形式でお願いしました。メンバは、僕にとっては定番である kazuhito_mさん,Hidari0415さん,USHITO Hiroyuki / kesさん。ありがとうございます。

Visual Studio Live Shareの実験→zoomのボイスチャットに変更

マンガ読んだ!!は全てVisual Studio(以下VS)で開発しています。モブプロするなら Visual Studio Live Share(以下VSLS)がベストかなと思いつつ一度も試したことがなかったので、今回はこの実験も兼ねました。他の人がVisual Studio Code(以下VSC)だったので、Vs vs VSCで試してみました。音声チャットも出来そうなのは以前見た記憶があったのでとりあえず他のツールの検証なしにいきなりVSLSを使ってみました。音声に関してはVSCは使えてもVSが非対応だったので、zoomのボイスチャットを併用しての実験になりました。結論から言うとVs vs VSCでのVSLSはうまくいかなかった感じです。何度か編集した所が何個も増幅した感じになったりして、同期自体がおかしいのか良くわからない状況になり、最終的には自分のVS以外は全て接続を切って、zoomのボイスチャットのみで進行する形になりました。ちと残念。

自分が書いていたSPA用のテスト

今回準備に自分が作っていたのはSeleniumを起動させて、起動した画面のタイトルが正しいかのテストのみです。ただBlazorでもindex.htmlだけは静的に決まっているのでそのタイトルが正しいのかのテストでしかなくSPAを全く考慮していません。SPA的に画面が切り替わったことをチェックするテストを書こうとして色々悩んだと話しました。で、それを言ったら、まず待つものをどこにどうやって定義するべきかを決める所からという話になりました。自分的には各ページ毎にclassで判定用タグを仕込んでいく形になるかなと思っていました。最初にDOMを書き終わったというイベントが取れるかという話になりました。Blazorにはライフサイクルイベントメソッドがあって、OnAfterRenderAsyncがあります。ならフラグはこのタイミングで書き換えるべきとなりました。次にそれを書くべき場所は何処だろうとなりました。body要素の中が良いだろうとなって、ここでさらに僕の疑問を聞きました。

タグで使うべきはclassかidか

それはidとclassのどちらを使うべきかです。これに関してはみうみう氏に明確な答えをもらいました。対象が一位になるならid、そうでなければclass。で、今回作るものは誰が使うか?テストが使う。逆に言えばテスト以外は使わない。つまりid一択で良い。なるほど!と思いました。例えばデザインで使うのであればそれを他にも充てたくなるのでidになることは少ないことも分かりました。明確な定義が分かってスッキリしました。ロジカルに考えば当然行きつく考え方かもしれませんが、それを思いつかなかった僕としてはこの話が聞けただけで、今回やった価値がありました。ありがとうございます。次にidのvalueをどうするかとなって、data-stateを進められました。これがあるとjsでdataset.stateを使えば簡単に書き換えられる。なるほど知らなかったのでこれは便利だなと思いました。ただ、ここでBlazor固有の問題がありました。

Blazorでの問題

Blazorだと共通のBodyを動的に書き替えるのがそれほど簡単ではないのです。各ページから共通要素への書き換えは出来ないわけではないけれど面倒です。jsならdocument.getElementById('wait').dataset.state = 1;で済むのに。と言うわけでここはBlazorからjsを呼ぶことにしました。これでページが切り替わったときに、IDが1になるのを待てば、SPAでページが切り替わったことがテストできるはずです!ところが実際に書いてみるとWebDriverWaitの待ち受けが上手くいきません。NoSuchElementExceptionで落ちてしまいます。wait.IgnoreExceptionTypes(typeof(NoSuchElementException));を書いても駄目。これは全員はまってしまいました。ここでUSHITO氏がExpectedConditions使ってみたらという話になって、使ってみると確かに例外が出ませんでした。ただExpectedConditionsは警告が出るぐらい古い書き方。んー。一旦これで行くことにしつつもっといい書き方がないかは宿題となりました。これで一応画面の切り替えを待ってタイトルのテストを書くことが出来ました。この時点で2時間程度たってしまったので、終わりにしました。

開発環境の宿題

それともう1個宿題。環境面の問題として、Visual Studioでテストを書くにあたって、ローカルでテストをしようと思ったらローカルでサーバーを立ち上げる必要があります。開発中はBlazorのServerでデバッグ起動すれば勝手にサーバーが立ち上がって、ブラウザを終了すれば勝手に閉じてくれます。自分はローカル開発ではこれ以外でやったことがなかったので、テストの時ローカルでサーバーを立ち上げておく方法が分かりませんでした。なのでVSをもう1個起動して、それをデバッグ実行して、テストするようにしました。ところがこの方法だと、クライアント側も書き換えたい時にファイルがロックされてビルドが通らない状態でした。なのでサーバー側を閉じて、書き換えをして、終わったらまたサーバーを起動してというかなり面倒な状態になりました。この状態で今後も続けるのはちょっとあり得ないなとなったので、解決策を次回までに探っておくことになりました。

まとめ

結局今回はBlazorでシステムテスト1個がなんとなく動く状態になりました。画面の切り替えはidが定義されていてそのstateが変化したことで待ちが出来ます。1個できればあとは量産ですが、まだそこまで練られた感じでもありません。コードだけでなく、開発環境としても現段階では無駄が多いので、次回までに宿題を解決して、量産出来る状態になればと思いました。当初予定したモブプロにはならなかったけれど、思考を言葉にして、それをディスカッションしながらコードを書いていく体験は、気づきも多く、またなにより楽しかったです!これがモブプロなのかは定義が分かってないのですが、自分的には名前を付けるならモブレビューしながらプログラミングかなと思いました。と言うわけで2週後に第2回をやります。