テスト用のオブジェクトを簡単に作れるFactoryJSというライブラリを作った
この記事は「TSKaigiサブイベント #1 フロントエンド」にて登壇した内容の文字起こしです
本記事で紹介しているOSSはこちら👇️
登壇者
TypeScriptでバックエンドのテストを書くときの課題
早速なんですが、みなさんテストを書いてますでしょうか?
昨今では、TypeScriptでバックエンドを書けるのが普通になってきました。バックエンドで利用できるORMやフレームワークも充実してきています。
バックエンドはフロントエンドに比べてデータベースを扱ったり、重要なロジックが含まれているので、しっかりとテストを書きたいというモチベーションが湧いてくると思います。
そこで課題になるのが、テストデータの準備ですね。
例えば、Prismaで「ユーザーが管理者ならtrueを返す」というシンプルな関数を作ったとします。テスト対象のコードがシンプルなので、テストもシンプルに書けると思うかもしれません。
しかし、上記のテストコードを見てもらうとわかるとおり、ユーザーデータの作成する処理で数行のコードを書く必要があります。テストと関係のない初期値も入れなければなりません。
簡単なテストケースならいいのですが、複数のデータを作る時にはコードが煩雑になり、読みづらくなるなる可能性があります。
多言語ではどのように対処しているのか?
RubyではFactorybot、Pythonではfactory_boyというライブラリがあります。
Factorybotを利用すると、ユーザーが作成する処理を「create(:user)」のような形で記述することができます。TypeScriptユーザー側からするとかなりうらやましい状況です。
TypeScriptで似たようなライブラリはないのか?
TypeScriptにもFactorybotのようなはないか?というのを調べてみたのですが、「あるにはあるが、決定的なライブラリはない」という状況でした。
昔に作られたライブラリで似たようなものはあったのですが、そもそもTypeScriptがない時代に作られたものだったり、PrismaのみサポートされていてDrizzleのような最近のORMはサポートしていなかったりすることが大半です。また、Factorybotに比べて機能が不足しているものが多い状態です。
複数のORMに対応していて、型をしっかりサポートし、ファクトリーボットの機能をなるべく網羅しているようなライブラリーが欲しいというので、今回自作することにしました。
TypeScript向けに「テスト用のオブジェクトが作れる」ライブラリをつくることに
実際に作ってみたのですが、思っていたより簡単ではありませんでした。
Factorybotの場合、Rubyには型がないので値の参照が柔軟にできるのですが、TypeScriptだと型があるため同じような実装は難しいという制約があります。
いくつか試行錯誤した結果、今回完成したのがFactoryJSというライブラリーで、今回発表する内容になります。
FactoryJSの使い方
実際の使い方はFactorybotと似たような形になります。プロパティのデフォルト値を設定して、データベースへの保存方法を指定するだけです。デフォルト値を上書きして使うことも可能です。
FactoryJSを使用する前後で比較してもらうとわかりやすいのですが、従来の方法に比べてコード量が減っているのがわかります。
また、このテストではロールのプロパティが関係しているというのが分かりやすくなり、テストの保守性と読みやすさが向上するメリットがあります。
また、基本的には、Factorybotの主要機能はサポートしています。Factorybotにある機能はだいたい揃っているかと思います。
PrismaスキーマからFactoryを自動生成するプラグイン
ここまででも十分に便利なのですが、もっと楽をしたいという気持ちが私にはありました。そこで、Prismaのスキーマから自動でファクトリーを生成するライブラリを追加で作ることにしました。
Prismaのスキーマをもとにして適切なデフォルト値をもったFactoryが自動で生成されます。
FactoryJSは社内でも利用され始めている
個人開発で使っていたものですが、社内でも使えそうだということで、現在では一部のプロジェクトで利用されています。
現在、700以上のテーブルがあるスキーマが存在するのですが、これをもとにファクトリーを自動生成しても今のところ問題なく使えている状況です。
FactoryJSはOSSとして公開しているので、興味がある方は是非見ていただければと思います。
▼noteの技術記事に興味があるかたはこちら