はてなブログで使われているフロントエンドのテストツールを統一した話

はてなでエンジニアアルバイトをしているid:wafuwafu13です。はてなブログのフロントエンドで使われているテストツールの統一を2021年11月頃から進めてきましたが、この8月に完了したので振り返りたいと思います。

はてなブログのフロントエンドに残された秩序の乱れ

2020年のid:nanimono_demonaiさんの活動により、はてなブログのフロントエンドのテストはPhantomJSとKarmaを撤退し、Jestに移行されました。

はてなブログのフロントエンドに秩序はもたらされたのか - Speaker Deck

これによって秩序がもたらされたものの、Node.jsのassert moduleによるアサーションや、Sinon.JSによるモックが残存していたり、EnzymeとReact Testing Libraryが混在していたり、秩序が少し乱れている状態でした。

こうしたフロントエンドのモダン化に課題を感じていたため、次の2つを目標に移行作業を進めることにしました。

  • アサーションとモックをJestに統一する
  • Enzymeを撤退して、React Testing Libraryに統一する

テストツールを統一する理由とツールの選定

テストツールを統一するメリットとして挙げられるのが、学習コストとメンテナンスコストの削減です。テストツールが統一されていると、テストコードを読む際にも書く際にも、学習で参照するドキュメントが少なくなります。

メンテナンスに関しては、例えばassert.deepEqualがv16.0.0, v14.18.0からLegacyになっていたのに、使われ続けてる状態でした。テストツールが統一されていれば、メンテナンス対象が絞られ、迅速に対応しやすくなります。

それ以外のメリットには、facebook/jest Issue #7547にあるように異なったテストツールを併用すると副作用が生じることがあり、これを防ぐことができます。

Enzymeを撤退する理由としては、「Why should I use React Testing Library?」にあるように、テストの信頼性を高めたいということがあります。さらに「Enzyme is dead. Now what?」にあるEnzymeの存続への懸念や、Reactのアップデートをブロックしていたという事情があります。

Jestについては、npm trendsでAVAやChaiなどと比べてもダウンロード数が多く、外部からの開発が活発で、オーナーシップもMetaからOpenJS Foundationに移行するなど安心して使い続けられるだろうと考えています。

移行をどう自動化したか(しなかったか)

Node.jsのassert moduleによるアサーションは1,033箇所で使われており、手作業での置き換えも可能だけどモチベーション的には不可能といった状態でした。また、AVAやChaiなどからJestへの移行に推奨されているjest-codemodsがNode.jsのassert moduleに対応していなかったので、移行ツールを自作することにしました。

jest-codemodsのようにjscodeshiftを用いる方法もありましたが、私は趣味でbabel-handbookを翻訳したりBabelにちょこっとコントリビュートしたりしていてBabelに馴染みがあったので、Babelプラグインを作成する方針で進めました。バグがいくつか残ったものの、短時間でサクッとBabelプラグインを仕上げることができ、バグの部分は手作業でカバーして置き換えを完了させました。

wafuwafu13/node-assert-2-jest-expect: Transform Node.js assert into Jest expect

実装の概要は、次のブログににまとまっているので興味ある方はお読みください。

www.mizdra.net

Sinon.JSも同様に自作ツールでの置き換えを検討しましたが、使われているのが209箇所でassert moduleより少なかったため、手作業で完了させました。

実は、jest-codemodsのSinon.JSへの対応が置き換え完了のちょうど後の時期だったので試すことはできませんでしたが、もし自分が使っていたら壊れていたであろう部分を見つけて修正することはできました。

[sinon] Implement `stub.resetBehavior()` and `stub.resetHistory()` by wafuwafu13 · Pull Request #364 · skovhus/jest-codemods

Enzymeの置き換えは「How to migrate from Enzyme to React Testing Library?」にあるように、段階的にコツコツと進めていきました。

余裕のあるスケジュールで小分けして作業を実施

私の所属は、2020年8月から2021年10月までがはてなブログで、2021年11月からシステムプラットフォーム、2022年4月から現在はMackerelチームと変遷しています。テストツールの統一作業は2021年11月に開始したので、はてなブログチームの所属ではない状態で進めました。

チームを離れてから着手した動機は、フロントエンドのモダン化への課題感もありますが、単純にフロントエンドを書き続けていたいというものでした。チームのスクラムから離れた状態なのでプロダクションコードに手を加えるのではなく、直接的にプロダクトの品質に影響を与えないテストコードの課題を解決しようと踏み切りました。

自主的に始めたプロジェクトのため、改善する範囲を定めただけで特にスケジュールは組んでおらず、メインで所属しているチームのスキマ時間で完了させることだけを目標に進めてきました。実際、所属チームでの作業が詰まったときの気分転換や、レビュー待ちの時間が有効活用できました。また、MackerelチームではReact Testing Libraryが使われていたので、Enzymeからの置き換えがスムーズにできました。

PRの作成方針としては、まずは2ファイルくらいを置き換えのサンプルとしてレビュー依頼に出して、置き換えの方針が固まったら小分けにしてPRを作成していくことにしました。一気に置き換えないことで、レビューの負担と、レビューで方針が変わった際の手戻りを削減することを意識しました。

Enzymeの置き換えは最終的に12分割になりました

はてなエンジニアのアルバイトは通年で募集中!

はてなインターンと比べると、はてなアルバイトの活動報告は少ないようなので書いてみました。はてなエンジニアのアルバイトは通年で募集されているので、夏でなくても応募できます。興味がある方は次のリンクを参照してください。