フロントエンドなエンジニアの皆さま、ご機嫌いかがでしょうか。
唐突な質問ですが、Internet Explorer 11というブラウザはお好きでしょうか。勿論大好きであられるかと存じ上げます。Webの歴史をまさにその身をもって築き上げてきた由緒正しきブラウザであります。唯一無二の王道です。昨今は様々なブラウザが溢れてあそばせております。しかし所詮それは一時的なこと。やがて全人類は母なるInternet Explorer 11の元へと還っていくことでしょう。
我々が目指したこと
Internet Explorer 11(以下、IE11)を目にすること、操作すること、その他あらゆる接点を限りなく減らしつつ、プロダクトがIE11でも動作可能なことの検証と保証を行いたい。
これを成し遂げるエンジニアリング的な手段、つまりIE11環境でのE2Eテストを自動化することを目指します。
環境
自動化を行うにあたり、何をするにもまずは環境を用意しなければなりません。IE11が動く環境です。
そして早速ですがこの環境こそがIE11環境自動テスト一番の問題と言っても過言ではないでしょう。なぜならIE11が動くということは、当たり前ですがOSとしてWindowsが動いていなければなりません。Linuxディストリビューションではだめなのです。
1年前ならここで既に諦めざるを得なかったかもしれません。しかし今は既に2020年です。Windows環境に対応したCI環境は十分手に届く範囲に登場してきています。
メドピア開発部が最もお世話になっているテスト環境はCircleCIです。そしてなんと、CircleCIでもWindows環境に対応を始めているではありませんか。
既にWindows対応のテスト環境は目の前にあったわけです。しかし不運なことに、この事実はこの記事を執筆中に発見しました。執筆中ということは、当然ながら当初の目的は既に果たしているわけです。今ネタバレをしましたが、つまり今回採用したのは慣れ親しんだCircleCIではありません。
IE11の全てを委ねるべく採用した環境は、Github Actionsです。
なぜGithub Actionsか、とてもいい質問です。「Githubで完結する」、「GithubがMicrosoft傘下になっていた」、「社内ではまだ導入事例も少なく目新しさがあった」、そこには色々な選ぶべき理由があります。
そしてこういう理由は後付けです。最初に目に入ってしまったからです。IE11でサービスが動いていなかった障害に傷心しながら「IE11 E2E」と適当なワードで検索したら偉大な先駆者達の功績が目に入ってしまったわけです。
今まで不可能だと諦め続けていたことが、「できる・・できるんだ・・っ!」という確信に変わった瞬間です。あとはもう勢いでやり切らざるを得ません。そして勢いのままに開発フローに導入し、勢いの落とし前としてこうして外部発信をして既成事実としていくわけです。
プロダクト概要
昨年11月にリリースした、「MedPeerスポット×リクルートメディカルキャリア」という医師向けスポット求人マッチングサービスです。 spot-rmc.medpeer.jp
プレスリリースはこちら。 medpeer.co.jp
求人マッチングサービスという特性上、求人情報の検索、応募フォームの入力、応募リクエストの送信あたりが動作してくれないと非常に困るクリティカルな機能となってきます。
プロダクト構成
今回ターゲットとしたプロダクトは、APIを提供するRuby on Railsによるバックエンドと、フロントエンドをSSR対応で配信するNuxt.jsという2枚看板な構成です(以下、Rails、Nuxt)。
Tailwind CSSの話題に終始した前回記事と同じプロダクトなので、お時間あればこちらもご覧ください。 tech.medpeer.co.jp
フロントエンドとバックエンドの橋渡し役となるAPIは、OpenAPIに乗っ取ってスキーマ定義を行い、openapi-generatorのtypescript-axiosを利用して型付きのクライアントSDK化しています。
このSDKは独立したリポジトリになっていて、スキーマ更新をpushするとSDKも最新化してくれるようCIを組んでいます。
あとはフロントエンドリポジトリ側でSDKのインストールやアップデートをしていけば、型で(ある程度は)守られたSDKを通してAPIとの連携が可能です。
問題
Railsが強めなメドピア開発環境からすると、フロントエンドが完全にRailsから分離された今回のプロジェクトはなかなかに攻めた構成でした。フロントエンド分離主義者の方々もきっと満足してくださるでしょう。
かくいう私も満足していた1人だったのですが、E2Eテストという観点からするとこの構成は大きな問題を抱えていました。
Rails主導な構成であればcapybaraを利用したFeature specが大体いい感じにしてくれるみたいです。実際メドピアではこれが大活躍していて、入社当初はFeature specによるテストの充実具合に驚いた思い出があります。
しかし困ったことに、今回のフロントエンド環境はRailsの支配下にありません。こういう状況で、E2Eテストをどう行うべきかという知見が社内に全くない状態でした。
このようなマイクロサービス気味構成におけるE2Eテストのベストプラクティスを一緒に考え、議論し、実現していってくれるエンジニアをメドピア開発部では絶賛募集中です。
今、私にできること
全てがうまくいくトータルオールインワンストップE2Eソリューションの実現は残念ながら成りませんでしたが、ある程度の妥協を許せばこんな私にもできることは残されています。
今回の目的に立ち戻ります。それは、「IE11での動作検証を自動化する」ことです。IE11固有の動作検証をしたいわけです。例えばIE11固有の仕様により、ajax通信用APIを提供しているだけのRails側機能が動作しないということはあるのでしょうか?
落ち着いてください、お気持ちは分かります。確かに無いとは言い切れないかもしれません。IE11の全てを疑ってかかりたい人生を送られてきた皆様のお気持ちは十分に分かりますが、それでもときには信じることだって大事なんです。
はい、信じました。これでまずはRailsが動作検証の対象から外れました。
Railsが関心範囲から外れてしまえばあとはもうフロントエンド原理主義者が好きにやるだけです。先ほどAPIとの連携部分は型で守られたSDK化していると紹介しました。つまりは型さえ守っていればモックに差し替えることは容易いわけです。
当初は登場人物が3人も居て途方に暮れていましたが、IE11で動作検証することを目的とするならば、Nuxtだけを検証対象にすればよいという状況に漕ぎ着けました。
Github Actions
Github Actions用ymlファイルの紹介です。
既に先人達が詳細に紹介してくれていて、特に大きな差分もないです。異なるのは、NuxtによるSSR環境を再現するために、テストランナー用のスクリプトを別途用意している点です。
続いてそのテストランナー用のスクリプトの中身です。
テスト対象となるNuxtサーバーの起動と、テスト本体を実行してくれるTestcafeの起動を担当しています。
Nuxtを裏で起動したままTestcafe(後述)を起動するという制御が必要だったので、非同期な処理が書きやすいnodeスクリプトを利用しています。
Github Actions職人であればNuxtの裏起動をもっとスマートな方法で実現できるのかもしれません。メドピアではGithub Actions職人もきっと募集しています。
なにやら怪しげなコメントがいくつか挿入されています。いずれも遭遇したエラーとそれを乗り越えた歴史です。
windows環境でspawnが使えない
spawn
というのは非同期で外部コマンド実行してくれる関数です。
IE11を動かすGithub Actionsは当然ながらwindows環境です。普段windows環境でnodeスクリプトを実行する習慣がないので油断していました。spawn
はcmd
経由でコマンドを実行する必要があるようです。
@nuxtjs/pwaモジュールが吐き出すエラーでジョブが落ちる
ERROR (node:5136) DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead
こういうやつです。その他環境ではエラーを吐いても特に問題なくNuxtのビルドは成功判定となってくれるのですが、なぜかGithub Actionsのジョブとして実行すると容赦なくエラー扱いで落ちてしまいました。
@nuxtjs/pwaモジュールを最新化すればエラーは消えるらしいものの、まだβバージョンということで躊躇し、nodeスクリプト内でGithub Actionsさんに気づかれないよう実行することで回避しました。
クロスブラウザでテストする場合だと毎回ビルドし直しになって効率悪いですが、今回の対象はIE11だけなのでここも割り切っていきます。
windows環境でnpmスクリプトに環境変数を渡せない
もう1件windows由来問題です。どうやらwindowsではNODE_ENV=production yarn build
のような環境変数の指定はできないらしいです。やはり普段触らない環境は知らないことだらけですね。
cross-envというパッケージを使うとさくっと指定できるようなのでnpx
でさくっと使わせていただきます。
Testcafe
環境が出揃ったところで今更ですがテストランナーの紹介です。今回採用したのはtestcafeです。
採用理由は、IE11でさくっと動いたからです。第一目的はIE11における動作検証であって、プロダクトの仕様や機能検証といった大層なものではありません。さくっと仕組みを作って多大な労力を削減する。できそうなことが分かったのですからそのまま勢いで組み上げます。
テストコード抜粋はこんな感じです。できる限りE2E専用のid
やclass
は入れないほうがメンテは楽な気がします。文言変更で壊れたらそのときは諦めて都度直しましょう。
なにやらresizeWindow
という怪しげな関数があります。これはTestcafeに限った問題ではなくIE11利用のE2E全般の問題らしいですが、IE11では画面外要素はなぜか存在しない判定をされてしまうらしいです。
全盛期の彼ならその理由を躍起になって深掘っていったかもしれません。そんな彼もIE11に打ちのめされ尽くした今となっては、目の前の現実をただ受け入れるだけのマシーンです。そういうものです、目の前で起きていることは紛れもない現実なのです。
ただし開発環境のfirefoxやchromeなどで実行するときはサイズが大きすぎると怒られるので、申し訳程度に分岐を入れておきます。
成し遂げたこと
かくして、IE11で我々のプロダクトが動作することの検証は自動化に成功しました。E2Eのテストカバレッジは相当少なく、おそらく10%にも届いていないです。しかしながら、最も重要なトップ画面から応募完了までのルートをIE11で通過できることが自動テストで保証されている安心感は凄まじいです。
dependabotでnpmパッケージアップデートのPRが飛んできても、それがbabel関連パッケージだったとしても、自動テストが元気よく動いてIE11環境の動作検証を行ってくれています。
結局スタイルチェックで実機IE11チェックは必須なんですがこの記事が皆様のIE11ライフに少しでも貢献できましたら幸いでした。
(☝︎ ՞ਊ ՞)☝︎是非読者になってください
メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!
■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/
■開発環境はこちら