🧪

Testのためだけに関数をexportしたくない【TypeScript🔥】

に公開

テストのためにexportしている辛さ

他のファイルから参照されないように private関数として定義したい関数なのに、テストのためだけにexportしないといけないのは辛い。

hoge.ts
// 責務を分離するために関数に切り出したが、hoge.ts内部に閉じたprivate関数でいたい。
// なのにテスト用にexportしないといけない、、
export const privateMethodForHoge = (arg: string): string => {
  // 省略
}

// これは外側のファイルから呼び出されるつもりの関数
export const doHogeForPublicUse = (arg: string): string => {
  // 中略
  return privateMethodForHoge(arg)
}

案1: In-Source Testingを使う

https://vitest.dev/guide/in-source.html
https://speakerdeck.com/taro28/vitestnoin-source-testinggabian-li

ソースコードと一緒にテストがかける。

hoge.ts
const privateMethodForHoge = (arg: string): string => {
  // 省略
}

if (import.meta.vitest) {
  const { it, expect } = import.meta.vitest
  it('privateMethodForHoge', () => {
    const input = "fuga"
    const expected = "hoge"
    const actual = privateMethodForHoge(input)
    expect(actual).toBe(expected)
  })
}

メリット

  • 本来したくなかったexportが不要になる。
  • コードが見づらいと思いきや、テストコードは仕様書を兼ねるという考え方を持つとテストとコードがセットで書かれているのは逆に閲覧性が高いのかもしれない。

デメリット

  • コードが見づらい。

案2 テスト用として明示してexportする

__test__みたいなめっちゃテストっぽいobjectでexportしておくという方法

hoge.ts
const privateMethodForHoge = (arg: string): string => {
  // 省略
}

// テスト用のobjectとしてexportする。
export const __test__ = {
  privateMethodForHoge,
  // 他にもこのファイル内でテストしたいprivate関数はここに追加する
};
hoge.test.ts
import { describe, expect, it } from "vitest";
import { __test__ } from "./hoge";

const { privateMethodForHoge } = __test__;

describe("privateMethodForHoge", () => {
    it('fugaはhogeになる', () => {
    const input = "fuga"
    const expected = "hoge"
    const actual = privateMethodForHoge(input)
    expect(actual).toBe(expected)
  })
})

メリット

  • vitestの仕様がソースコード側に漏れ出ないので綺麗な気がする
  • exportしていることには代わりないが、__test__というあからさまな名前にしておくことで Codex君やClaudeCode君に気づいてもらえる。

デメリット

  • なれない書き方でコツがいる? → AGENTS.mdに書いてAIに徹底させれば良し

おわりに

案2を使っていこうと思います。

株式会社Digeon

Discussion