スナップショットテストの可読性改善:`pretty`ヘルパーによるマージコンフリクト軽減

tailwindlabs/tailwindcss

VitestのインラインスナップショットでCSSの先頭と末尾に " が現れる問題を解消するため、pretty ヘルパー関数が導入されました。これにより、マージコンフリクト発生時の解消作業が簡略化されます。

背景

Vitestのインラインスナップショットは、期待値をバックティック内のダブルクォートで囲んだ形式で記録します。この仕様により、CSSを直接スナップショットに入れると先頭行と末尾行に " が付与され、マージコンフリクトの解消時に余計な考慮が必要になっていました。

具体的には、変更前のスナップショットは以下のような形式でした:

expect(result.css.trim()).toMatchInlineSnapshot(`
  "@layer utilities {
    .foo {
      color: #000;
    }
  }"
`)

CSSの先頭が "@layer 、末尾が }" のように " と結合された状態になるため、コンフリクトマーカーの解消時にこの引用符を意識しながら編集する必要がありました。PR著者はこの問題に「すでに十数回遭遇した」と説明しています。

また、空文字列を期待するテストで .toMatchInlineSnapshot() を使っていた箇所も問題でした。スナップショットの更新が「簡単すぎる」ため、バグによって何かが生成されても気づきにくいリスクがあります。

技術的な変更

packages/tailwindcss/src/test-utils/run.tspretty ヘルパー関数が追加され、テストヘルパー全体の出力形式が統一されました。

変更前:

export async function compileCss(...) {
  let { build } = await compile(css, options)
  return optimize(build(candidates)).code.trim()
}

export async function run(candidates: string[]) {
  let { build } = await compile('@tailwind utilities;')
  return optimize(build(candidates)).code.trim()
}

export function optimizeCss(input: string) {
  return optimize(input).code
}

変更後:

export async function compileCss(...) {
  let { build } = await compile(css, options)
  return pretty(optimize(build(candidates)).code)
}

export async function run(candidates: string[]) {
  let { build } = await compile('@tailwind utilities;')
  return pretty(optimize(build(candidates)).code)
}

export function optimizeCss(input: string) {
  return pretty(optimize(input).code)
}

export function pretty(input: string) {
  input = input.trim()
  if (input === '') return ''
  return `\n${input}\n`
}

pretty 関数はシンプルな実装です。トリム後の入力が空文字列なら '' を返し、そうでなければ入力を \n で前後に挟みます。これにより、スナップショットの外側の " からCSSが分離されます。

この変更によって、スナップショットの見た目は以下のように変わります:

expect(pretty(result.css)).toMatchInlineSnapshot(`
  "
  @layer utilities {
    .foo {
      color: #000;
    }
  }
  "
`)

CSSの先頭行が " と結合されなくなるため、コンフリクト解消時にCSS行だけを見ればよくなります。また、空出力の期待には .toMatchInlineSnapshot() ではなく明示的な .toEqual('') を使うよう変更され、意図しない出力を見逃しにくくなっています。

設計判断

css タグドテンプレートリテラルを使うアプローチ も検討されましたが、採用されませんでした。

PR本文では、String.raw として実装した css タグを使いスナップショットをCSSとして直接記述する案が言及されています。エディタのシンタックスハイライトやPrettierによるフォーマットも活用できる点で魅力的ですが、2つの問題がありました。1つ目はPrettierによるフォーマットが入出力の不一致を生む可能性があること、2つ目はVitestがバックスラッシュをダブルエスケープするため \[color:red\] のようなセレクタでスナップショットが壊れることです。カスタムスナップショット環境を使えば技術的には実現可能ですが、間接層が増え、テストの信頼性に微妙な影響を与える可能性があるとして見送られています。

結果として、pretty による \n の挿入という最小限の変更が選ばれました。既存のテストヘルパー(compileCssrunoptimizeCss)の内部で pretty を呼ぶことでほとんどのテストが自動的に新形式に移行でき、各テストファイルへの変更を最小化しています。

まとめ

pretty ヘルパーの導入は、テスト出力のフォーマットをわずかに変えるだけでマージコンフリクトの解消コストを下げ、空出力テストの安全性も高める実用的な改善です。テストインフラを整備することで、コードベースの長期的なメンテナンス性が向上します。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
07b3f150

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術的な変更・設計判断(各論)→まとめ(結論)という構成が明確で、ガイドラインに完全に準拠しています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```typescript:path/to/file.ts)およびPR番号のリンク記法([PR #20013](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

内容はVitestのスナップショットテストに関するもので、専門知識を持つエンジニアを対象としており、過度な説明がなく適切です。

パラグラフ・ライティング ⚠ WARNING

トピックセンテンス・1段落1トピック・段落長

全体的にトピックセンテンスが明確で読みやすいですが、「背景」セクションの一部で技術的な説明とPR著者の所感が1つの段落に混在しており、1段落1トピックの原則からわずかに逸脱しています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコードブロック(`pretty`関数の実装、ヘルパー関数の変更点)は、提供されたDiff情報と完全に一致しており、正確に引用されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「インラインスナップショット」「タグドテンプレートリテラル」「Prettier」など、PRで言及されている技術用語が文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

`pretty`ヘルパーが改行(\n)を挿入することで、スナップショット内のCSSと引用符を分離し、コンフリクト解消を容易にするという説明は、技術的に正確かつ論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

「すでに十数回遭遇した」という著者の経験や、採用されなかった`css`タグドアプローチの検討経緯など、記事内のすべての主張がPRのDescriptionによって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号「#20013」がフッター部分で正確に記載・リンクされています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは、PRの主題である「Improve snapshot tests」の具体的な内容(`pretty`ヘルパー導入による可読性改善とコンフリクト軽減)を的確に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事には、バージョンサポート状況やリリース日程など、PR情報に基づかない外部知識は含まれておらず、事実に基づいた記述が徹底されています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

PR内の「I ran into this a dozen times already」という表現を「すでに十数回遭遇した」と正確に訳出しており、時間表現の歪曲はありません。