bun testが速いのでvitestから置き換えたらめちゃ高速化された

2024/12/17に公開

きっかけ

  • ユニットテストはvitestを使ってます
  • まあ十分速い
  • でもCIで全testを回すとけっこう時間がかかる
  • bunのtestが速いらしい。置き換えよう

置き換えた結果

before (vitest)

  • 1000弱のtestを回すのに2分44秒かかってた

after (bun + vitest)

  • 9割方のtestをbunで実行して2秒。速すぎる

  • bunに移行が難しかった一部だけvitestで実行して7秒

bunってどうなの?

https://bun.sh/

  • どうなんですかね?
  • State of JavaScript 2024: Testing によればother testing toolsの中では3位でした
  • Develop, test, run, and bundle ができるオールインワンツールですが、今回はこのtestの部分だけ使うことにしました

bun run testとbun testの違い

  • とりあえず bun test を実行してみたらけっこうエラーが出て全然ダメでした
  • で、vitestのドキュメントを見ると bun run test 使ってねと書いてたのでそうしたら通りました。よかった
  • …と思ったけど全然速くなってない。これだとそもそもbunで実行されないので何も変わりません

bunで動くようにする

  • エラーを見ていって順に直していきました

global importをやめる

  • これjest時代から引きずってたんですが、expecttestなどのAPIをグローバルimportしていてbunはそれを解釈しないのでエラーになってました
  • vitest.configのglobalsを無効化し、各testファイルで明示的にimportするようにして解消しました

dom test

  • dom testが必要な場合、bunでは別途設定が必要です
  • https://bun.sh/docs/test/dom
  • happy-domを入れて設定ファイルを追加すればokです

タイムゾーンのあるtest

  • dateをstring化した場合のtestなど実行環境のタイムゾーンによって結果が変わりますが、このへんvitestのものと違いが出ました
  • これはtestファイル中にprocess.env.TZ = 'Asia/Tokyo'などと指定すればokです

import元は勝手にbun:testに書き換わる

https://x.com/__syumai/status/1700160108053811342

  • import {} from 'vitest'と書いていてもbun testで実行するとvitestの部分がbun:testとして解釈されるので書き換えなくてもそのまま動きます
  • まあ最終的にbun:testに書き換えましたが

mock関数の置き換え

  • import元は書き換えなくてもいいと書いたばかりですが、mock関数は互換性がないので書き換える必要がありました
import { vi } from `vitest`
vi.fn(()=>{})
vi.mock('foo', () => {})
import { mock } from `bun:test`
mock(()=>{})
mock.module('foo', ()=>{})

bunで対応できてないところもある

じゃあどうするか?

  • bunとvitestは並列で回すようにしました
  • 要はbunで実行するtestとvitestで実行するtestが切り分けられれば良いです
  • testファイルと認識されるのは*.test.ts*.spec.tsですが、bun側にはマッチパターンをカスタムする設定が無いようなのでvitest側を変更しました
test: {
  include: ['**/*.vitest.?(c|m)[jt]s?(x)'],
}
  • vitest.config.jsのtest.includeのところをtest.tsではなくvitest.tsに変更し、testファイルもそのようにリネームしました

周辺ツール

エディタ拡張

  • vitestの拡張と同じような感じで各testの上に実行ボタンが出ます
  • vitestのほうは専用のUIパネルですが、bunのほうは統合ターミナルにコマンドを出力して実行するのでけっこう素朴な感じです。historyに積まれるのがちょっと面倒かも

ツールマネージャー

  • フロントエンドのツール管理はvoltaを使ってたんですが、bunは対応してない(pnpmも)ので置き換えることにしました
  • miseを使うといろいろ良さげだったのでそちらにしてます

まとめ

  • ほんと速い
  • productionに使っていいのか?
    • まあいいんじゃないですか
Studio Tech Blog

Discussion