結論:単体テストとは「関数やクラスが期待どおり動くかを、コードで自動的に確かめる」しくみです。目的は品質チェックというより、〈毎回手で動作確認する手間をなくす〉ことと〈壊したことにすぐ気づける〉こと。書き方は「準備 → 実行 → 検証」の3行だけなので、最初の1本は今日書けます。
「テストコードって、余計に時間がかかるだけでは?」――最初は誰もがそう思います。実際は逆で、手作業の動作確認を毎回やる時間のほうが圧倒的に高くつきます。この記事では、単体テストの考え方と最初の書き方、そして初心者がつまずくポイントに絞って説明します。
単体テストとは何か
単体テスト(ユニットテスト)は、プログラムの小さな部品ひとつ(関数・メソッド・クラス)を切り出して、「この入力を与えたら、この結果になるはず」をコードで書いたものです。
// 考え方の骨格(言語を問わず同じ)
準備:テスト対象と入力データを用意する
実行:対象のメソッドを1回呼ぶ
検証:戻り値や状態が期待どおりか確かめる
この3ステップは AAA(Arrange-Act-Assert)と呼ばれ、言語やツールが変わっても形は変わりません。用語としての整理は テスト|Wiki用語集 にもまとめてあります。
なぜテストを書くのか(3つの実利)
1. 手作業の動作確認を捨てられる
テストがないと、変更のたびにアプリを起動し、画面を操作し、目で結果を確かめることになります。1回3分でも、1日に何十回もやれば大きな時間です。テストはその手順を機械に肩代わりさせるもので、実行は一瞬です。
2. 壊したことにすぐ気づける
コードは、直したつもりの場所と関係ないところが壊れます。テストがあれば、壊れた瞬間に赤くなって教えてくれます。これは後述の CI/CD と組み合わせると効果が跳ね上がり、「壊れた変更がマージされない」状態を作れます。
3. 安心してリファクタリングできる
動いているコードを整理するのは怖いものです。でも外から見た振る舞いを固定するテストがあれば、中身をいくら書き換えても「テストが緑のまま=壊していない」と分かります。リファクタリング|Wiki用語集 もあわせて。この感覚は文章より体験が早いので、リファクタリングをテストで支える をブラウザで実際に動かしてみてください(無料・登録不要・環境構築なし)。
Red-Green-Refactor:テストを先に書く回し方
テスト駆動開発(TDD)は「実装より先にテストを書く」進め方です。3拍子のリズムで回します。
- Red:まだ存在しない機能のテストを書く。当然失敗する(赤)。
- Green:そのテストを通すだけの、最小の実装を書く(緑)。
- Refactor:緑のまま、コードを整える。
先にテストを書く意味は「テストを増やすこと」ではありません。先に仕様を言葉にすることにあります。「この関数は、空文字を渡されたらどうなるべきか?」をテストとして書いた瞬間、実装の前に仕様が決まります。だから実装が迷子になりません。
用語の定義は TDD|Wiki用語集 に、実際の回し方は TDDとは ― Red-Green-Refactor にあります。この回はブラウザ上でC#をそのまま実行できるので、赤いテストが緑に変わる瞬間を自分の目で確認できます。同じ内容をコースの入口として扱っているのが TDDの回し方をおさらいする です。
テストフレームワークの記法を覚える
実務では自作の判定ではなく、テストフレームワークを使います。名前は言語ごとに違いますが、書くことはほとんど同じです。
| 言語 | 代表的なフレームワーク | よく使う書き方 |
|---|---|---|
| C# | MSTest / xUnit / NUnit | テストクラスとテストメソッドに印を付け、Assert で検証 |
| Java | JUnit | @Test を付けたメソッド、assertEquals などで検証 |
| Python | unittest / pytest | テスト関数を書き、assert で検証 |
記法の読み方は xUnitの記法 が分かりやすく、そのまま実行して試せます。Java 側で学びたい人は Java MVVMコースのTDD入門 から入ると、JUnit の書き方をブラウザ上で動かしながら覚えられます。
何をテストして、何をテストしないか
初心者がいちばん迷うのがここです。判断基準はシンプルで、「壊れたら困る判断ロジック」だけを狙うことです。
テストする価値が高いもの
- 条件分岐や計算がある処理(料金計算、バリデーション、並び替え、状態遷移)。
- 境界値(0件のとき、1件のとき、上限ちょうど、空文字、
null)。 - 過去にバグが出た箇所。同じバグの再発を止める番人になります。
書かなくてよい/書きにくいもの
- 値を入れて取り出すだけのプロパティ。
- フレームワークやライブラリの機能そのもの(それは作者がテスト済み)。
- 画面の見た目の細部。ここは自動テストの費用対効果が下がりやすい領域です。
具体例で見たいなら、値の正しさを守る ValueObject のテスト と、生成時のバリデーションを固める Factory をTDDで実装する回 が分かりやすい題材です。どちらもブラウザで実行できます。
モック(Fake / Moq / Mockito)が要る場面
テスト対象が外の世界(データベース、ファイル、時刻、ネットワーク)に依存していると、テストが遅くなったり、実行するたび結果が変わったりします。そこで「本物の代わりに、テスト用の偽物を差し込む」のがモックの考え方です。
順番に理解すると迷いません。
- まず手書きの偽物(Fake) を作る。インターフェースを実装した、メモリ上だけで動く簡易版です。→ Fake ― FakeTaskRepositoryでテストを書く
- 次に、その手間を自動化するモックライブラリを使う。C# なら Moq、Java なら Mockito です。→ Moq ― モックライブラリで手動Fakeを自動化する / Mockito ― モックライブラリで手書きFakeを自動化する
- そもそも差し替えられる設計にしておく。それが依存性注入です。→ 依存性注入(DI)とコンストラクタインジェクション
Moq を単体で先に見たい場合は Moq ― モックで依存を差し替える が短くまとまっています。
つまずきやすいところ
- テストが書けないのは、たいてい設計のせい。
newを直接書いていたり、静的メソッドで時刻を取っていると差し替えられません。見分け方は テストしにくいコードの見分け方 ― 静的依存とnewの直書き にまとまっています。「テストしづらい」は設計を見直すサインです。 - 実装の中身をなぞるテストを書いてしまう。内部の呼び出し順まで固定すると、リファクタリングのたびにテストが壊れます。検証するのは外から見える結果にとどめる。
- 例外の扱いを混同する。「例外が投げられること」もテストできますが、例外処理そのものの書き方は別テーマです。例外処理とは?try / catch の使い方 を先に読むと整理できます。
- 全部を一度にテストしようとする。まずは1つの関数に1本。増やすのは後からで構いません。
学ぶ順序(おすすめ)
- TDDとは ― Red-Green-Refactor でリズムを体験する。
- xUnitの記法 で書き方を覚える。
- TDD実践 ― 仕様変更に立ち向かう で「仕様が変わったときの守り」を知る。
- C# MVVMコース を通しで進め、Entity → Factory → Repository → Service → ViewModel を全部テストから作る流れを体で覚える。Java でやりたい人は Java MVVMコース が同じ構成です。
- 書いたテストを自動で走らせる仕組みへ進む → CI/CDとは?GitHub Actionsの使い方
C# MVVMコース・Java MVVMコースはどちらも全42回で、大半の回がブラウザ上でテストを実行して赤→緑を確認できる構成です。テスト用のツールを自分のPCに入れる必要はありません。
次に読む
- C# MVVMコース(全42回・TDDでアプリを育てる)
- Java MVVMコース(全42回・JUnitとMockito)
- C#デザインパターンコースのTDD章
- Service+Repositoryを通しでテストする ― 部品単体の次のステップ
- オブジェクト指向とは? ― クラス設計の基礎から固めたいとき
- C#独学ロードマップ / Java学習ロードマップ