第14章:互換性を守るテスト戦略(最低ラインでOK)🧪🛡️
—「更新したら壊れた😇」を“仕組み”で減らす章だよ〜!
14.0 この章のゴール🎯
この章が終わると、あなたはこうなれます👇✨
- 「互換性の事故」を テストで早めに発見できるようになる🔍
- 公開APIが変わったときに 意図した変更かどうかをチームで判断しやすくなる🧠
- 最小限のテストセットで、SemVer運用がグッと安定する📦🚦
14.1 互換性って、テストでどこまで守れるの?🤔
互換性の“壊れ方”はだいたい3種類(第4章の復習だね)🧩
- ソース互換:利用者コードがコンパイルできない💥
- バイナリ互換:実行時に落ちる💣
- 挙動互換:動くけど結果が変わる😵
この章では、特に ①と③を強くするのが目的だよ🛡️✨ (②は状況によるけど、ツール+実行テストで拾えること多いよ〜)
14.2 最低ラインの「互換性テスト」3点セット✅✅✅
“やりすぎない”が超大事!まずはこの3つだけでOK🙂🌷
✅セットA:公開APIの形を固定する(APIスナップショット)📌
「公開APIが変わったらテストが落ちる」仕組みを作る! → 意図せぬ破壊変更の混入を止めやすい🧯 (PublicApiGeneratorみたいな“公開API文字列化”の考え方がまさにこれだよ) (GitHub)
✅セットB:利用者コード風テスト(Consumerテスト)👩💻
“実際の使い方”で、コンパイルできるか・呼び出しが成立するかを守る💪 → オーバーロード追加の罠とかも拾いやすい💣
✅セットC:スモークテスト(最重要シナリオだけ)🔥
「利用者が一番踏む道」だけを 薄くテストする👣 → 挙動互換(結果が変わる問題)を最低限ガードできる🛡️
14.3 セットA:公開APIスナップショットテスト📌✨

何が嬉しいの?🥰
- publicメンバーの追加/削除/シグネチャ変更が起きたらすぐ分かる👀
- 「いつの間にか壊してた😇」が減る
- “変更が意図的か”をレビューで話せるようになる🧠
ざっくり導入イメージ🧪
- テストで「公開API一覧(文字列)」を生成
- それを “前回の正” と比較
- 差分があったら落ちる(=要確認)🚨
PublicApiGeneratorはまさにこの用途を想定してるよ (GitHub)
サンプル(xUnit想定)🧪
using System.Reflection;
using Xunit;
using PublicApiGenerator;
public class PublicApiTests
{
[Fact]
public void PublicApi_has_not_changed_unintentionally()
{
// ライブラリ側のアセンブリを指定(例)
var assembly = typeof(MyLibrary.SomePublicType).Assembly;
// 公開APIを文字列化
var api = assembly.GeneratePublicApi();
// ここでは超簡易に“固定文字列”比較の形を見せるよ
// 実運用では Verify / Approval テストでファイル管理するのが定番✨
Assert.Contains("public class SomePublicType", api);
}
}
実運用のコツ:
- 変更がOKなら「承認(approve)」して更新する
- 変更がNGなら差分を見て戻す この流れができると SemVerの判断が超ラクになるよ🙂✨
14.4 セットA強化:Microsoftの互換性チェックツール(ApiCompat)🔍🧰
「公開APIの差分を、ちゃんと“互換性”として判定」したいときに便利!
Microsoftの Microsoft.DotNet.ApiCompat.Tool は、アセンブリやパッケージの互換性チェックを行えるよ (Microsoft Learn)
何が嬉しいの?🥳
- “ただの差分”じゃなくて「互換性が壊れたか」を見やすい
- パッケージ(NuGet)としての比較もできる (Microsoft Learn)
超ミニ導入(ローカルツール)🛠️
dotnet new tool-manifest
dotnet tool install --local Microsoft.DotNet.ApiCompat.Tool --version 10.0.102
ちなみに .NET 10 のSDKは 10.0.102(2026-01のリリース情報)みたいに配布ページで確認できるよ (Microsoft) (最新のSDK前提で教材を組むと、チームの環境も揃えやすい✨)
14.5 セットB:利用者コード風テスト(Consumerテスト)👩💻💞

ここがめっちゃ大事!! “テストコード=利用者の書くコード” に寄せるのがコツだよ👀✨
やり方(おすすめ2択)✅
① サンプル利用者プロジェクトを同じソリューションに置く📁
MyLibrary(配る側)MyLibrary.ConsumerSamples(使う側の例)- CIで
buildが通ることを保証する🏗️
メリット:超かんたん、初心者でも回せる😊 拾える事故:シグネチャ変更、型変更、名前変更、オーバーロード地雷など💣
② “代表的な呼び出し”だけテストに書く🧪
- 重要APIだけ「こう使う」をテスト化
- 仕様が変わったらテストが落ちる → 気づける🙂
14.6 セットC:公開APIのスモークテスト🔥(薄いのに効く!)
“広く浅く”が正義👑✨ 特に 利用者の最短ルートだけ押さえよう!
スモークテストの作り方テンプレ🧯
- Arrange:最小の入力を用意
- Act:公開APIを1回呼ぶ
- Assert:最低限の結果を確認(例:nullじゃない、例外が出ない、代表値が一致)
例:例外と戻り値の最低保証🧪
using Xunit;
public class SmokeTests
{
[Fact]
public void Parse_should_accept_basic_input()
{
var result = MyLibrary.Parser.Parse("A=1");
Assert.NotNull(result);
Assert.Equal(1, result["A"]);
}
[Fact]
public void Parse_should_throw_on_invalid_input()
{
Assert.Throws<FormatException>(() => MyLibrary.Parser.Parse("???"));
}
}
ここで守ってるのは👇
- 「普通の入力で動く」😊
- 「ダメな入力のときの例外契約」⚠️(地味に互換性ポイント!)
14.7 “壊れやすい場所”に重点テストを置く🔍💣
全部テストしない!でもここは狙って守る🎯
優先度 高🔥
- 引数の null可否(受け入れる/返す)
- 例外の 種類・タイミング
- 既定値(デフォルト値)や挙動の微妙変更
- オーバーロード追加で解決先が変わる系😇
このへんは第8章の“地雷”と直結してるから、重点的にテストするとコスパ最強だよ💪💕
14.8 CIで「互換性ゲート」を作ろう🚦🤖
やることはシンプル!
-
dotnet testが通らない限りマージ不可🙅♀️ -
可能なら
- 公開APIスナップショットテスト
- Consumerビルド
- スモークテスト も一緒に回す✨
(ここまでできると「SemVerの番号ミス」が激減するよ📉)
14.9 AIの使いどころ🤖💡(この章、相性よすぎ)
AIは“テストの編集者”にすると強いよ〜!🧑🏫✨
使えるプロンプト例📝
- 「この公開APIの利用者が書きそうなコード例を5個作って。初心者〜中級で」
- 「互換性を壊しやすい変更点をレビュー観点で箇条書きにして」
- 「このバグ修正、PATCHで出すなら“守るべき挙動”をテストに落として」
- 「例外契約(どの例外を投げるか)をドキュメント+テストにする案を出して」
14.10 ミニ演習:公開APIのスモークテストを作ろう🧪🎀
お題🎒
あなたのサンプルライブラリ(第11章で作った想定)で、公開APIを3つ選んで👇
- スモークテストを各1本ずつ作る🔥
- そのうち1つをわざと壊す(例:引数名変更じゃなく、シグネチャ変更とか)💥
- テストが落ちたら「どの互換性が壊れた?」を言語化🗣️✨
提出物(成果物)📦
- ✅
SmokeTests.cs(3本) - ✅ 「壊れた理由メモ」(ソース/バイナリ/挙動どれ?)📝
- ✅ “次から防ぐならどのテストを足す?”アイデア1つ💡
14.11 この章のまとめ🎀✨
互換性を守るテストは、最初から完璧じゃなくていいよ😊 まずはこの順で“薄く”入れるのが勝ち🏆
- 公開APIスナップショット📌
- 利用者コード風(Consumer)👩💻
- 最重要スモーク🔥
これで「更新したら壊れた😇」が かなり減るはず!🛡️✨
次の第15章は、いよいよ 互換ポリシーを文章にするところだよ📘🖊️ テストで守れるようになったら、次は“ルール化”してチーム運用に落とす番だね〜!😊💕