In-source Testingとは、テストコードが実装コードと同じソースファイルに書かれているものである。Rustで有名なアプローチ。
先日から Vitest を何かと使うようになったが、VitestもIn-source Testingをサポートしている。JavaScriptのテストツールでは珍しいのでやってみた。説明としては次の記事のほうが断然詳しい。
// in-source test suites
if (import.meta.vitest) {
const { describe, it, expect } = import.meta.vitest;
describe('buildText', () => {
it('without note', () => {
const text = buildText({
notionBlockId: 'blockId',
url: 'https://example.com',
title: 'example',
});
expect(text).toBe('🔖 "example" https://example.com #laco_feed');
});
it('with note', () => {
const text = buildText({
notionBlockId: 'blockId',
url: 'https://example.com',
title: 'example',
note: 'note',
});
expect(text).toBe('note "example" https://example.com #laco_feed');
});
});
}
理解しておくべきポイントは以下
-
import.meta.vitest
の型定義は tsconfig のtypes
オプションに渡したvitest/importMeta
が持っている。 - テスト記述用のAPIは普通の静的なインポートではなく、
import.meta.vitest
から取得する。import.meta.vitest
が定義されていないときにif文全体がデッドコードとなることで、アプリケーションをバンドルするときにテスト関連のコードがまるごと除去できる。
所感
- テストを書くためにその関数の可視性がどうだとか悩む必要がないので、とにかくまずテストを書き始めるということをやりやすい。
- テストが実装とすぐ近くにあるので、テストファーストの開発スタイルには特に向いていると思う。
- 当然だがファイルが大きくなりやすいが、実装が増えたにしろテストが増えたにしろそれはつまりそのファイルの関心事が増えているということなので、関心を分離しろということになる。テストファイルがどんどん大きくなっていくのは見逃されやすいので、実装と同じファイルであることで「適切に困る」ことができそうだ。