3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第2回:「コンパイル中に動く?」〜TUnit の第一歩〜

3
Last updated at Posted at 2025-12-26

『先輩、私のコードがバグだらけです!〜TUnit と Moq で始めるユニットテスト入門〜』シリーズは、全 6 回を予定しています。

前回はこちら

登場人物

先輩 : Visual Studio のショートカットキーをピアノのように弾きこなす。「GUI でできることは GUI でやる」派。
後輩 : 新人開発者。黒い画面(コマンドプロンプト)を見ると動悸がする。Visual Studio の「デバックの開始」ボタンを押す瞬間が一番好き。

1. その前に……「混ぜるな危険」の鉄則

後輩:「よし、前回の話でテストの大事さはわかりました! さっそく今作っている『販売管理アプリ』のプロジェクトに、TUnit をインストールしちゃいますね!」

先輩:「ストップ!! ……危ない、それはラーメンの出前に 『味見用の小皿』まで入れて配達するようなものだぞ」

後輩:「えっ、どういうことですか?」

先輩:「理由は 2 つある。まず 1 つ目は、『ゴミが混ざるから』。お客さんが注文したのは『ラーメン(アプリ本体)』だよね? そこに開発者が使った小皿(テストコード)や洗剤(テスト用ライブラリ)が混入してたらどう思う?」

2-1.png
後輩:「うわ、絶対イヤです。クレームになりますね」

先輩:「だろ? テストコードは製品には含めちゃいけない。そして2つ目の理由がもっと怖い。『循環参照(じゅんかんさんしょう)』 の問題だ」

後輩:「じゅんかん……さんしょう? 難しそうな言葉が出ました」

先輩:「簡単に言うと、『調理場(アプリ)』が『検査室(テスト)』 に頼っちゃダメってことだ。もし同じプロジェクトに混ぜてしまうと、うっかり『テスト用の偽物の肉』を、本番のラーメンに入れてしまうかもしれない」

後輩:「あ! 本体のコードの中で if (テスト中なら) { ... } みたいに書いちゃうってことですか?」

先輩:「そう。それをやると、『検査室がないと料理が作れない』というおかしな依存関係(循環)ができあがって、コードがスパゲッティみたいに絡まって解けなくなるんだ」

後輩:「なるほど……。『料理』は『検査』を知らなくても作れるべきなんですね」

先輩:「その通り! 『テスト → アプリ』の一方通行を守るためにも、ソリューションの中で 『調理場(本体プロジェクト)』と『検査室(テストプロジェクト)』 は明確に部屋を分けるんだ。これはユニットテストの鉄則!」

2. 儀式(セットアップ)はマウスで優雅に

先輩:「というわけで、まずは 『テスト専用の新しいプロジェクト』 を作るぞ。Visual Studio ならマウスだけで完結する」

  1. ソリューションを右クリックして 「追加」>「新しいプロジェクト」 を選択
  2. テンプレートから 「コンソール アプリ (Console App)」 を選ぶ(C#用)
    ※TUnit はコンソールアプリとして作るのが基本なんだ。
  3. 名前は MyApp.Tests みたいに、末尾に .Tests を付けるのが慣習だ

後輩:「できました! ソリューションの中に2つのプロジェクトが並びましたね」

先輩:「次に、このテストプロジェクトに TUnit を入れるぞ」

1. MyApp.Tests プロジェクトを右クリック
2. 「NuGet パッケージの管理」 を選択
3. 「参照」タブで検索窓に TUnit と入力
4. 出てきたリストから TUnit を選んで 「インストール」 ボタンをクリック

後輩:「(カチッカチッ……)あ、これならネットショッピング感覚で簡単ですね!」
2-2.png

先輩:「仕上げに、『一方通行の矢印』 を引くぞ。テストプロジェクトの 『依存関係』 を右クリックして、『プロジェクト参照の追加』 から、本体のアプリ(調理場)を選んでチェックを入れるんだ」

後輩:「これで『検査室』から『調理場』は見れるけど、逆は見れない状態ですね! 準備完了です!」

3. 便利な属性 [Test] と IntelliSense

先輩:「まずは簡単な足し算クラス Calculator をテストしてみよう。こう書いてみて」

CalculatorTests.cs
using TUnit.Core; // 1. TUnitを呼び出す

public class CalculatorTests
{
    [Test] // 2. ここに便利な属性!
    public async Task Add_ValidParms_ReturnResult()
    {
        // 準備 (Arrange)
        var calculator = new Calculator();
        
        // 実行 (Act)
        int result = calculator.Add(1, 2);
        
        // 検証 (Assert)
        await Assert.That(result).IsEqualTo(3);
    }
}

後輩:「先輩、この [Test] ってやつ。……あれ? 書いたそばから色が付きました」
2-3.png

先輩:「そう、これが 便利な属性(Attribute) だ。Visual Studioの IntelliSense(インテリセンス) が TUnit を認識している証拠だね。これで『このメソッドはテストですよ』と宣言されたわけだ」

4. コンパイル中に動く「Source Generator」

後輩:「……あれっ!? 先輩、なんか変です!」

先輩:「どうした?」

後輩:「まだ『実行ボタン』を押してないのに、『テスト エクスプローラー』 の画面に、今書いた 足し算のテストAdd_ValidParms_ReturnResult が表示されてます! 今までのツールだと、一度ビルドして実行しないと認識しなかったのに……なんで!?」

先輩:「ふっふっふ。気づいたか。それが TUnit の最大の特徴、Source Generator(ソースジェネレーター) の力だ」

後輩:「ソース……ジェネレーター?」

先輩:「そうだな、もっとイメージしやすい例で説明しよう。『修学旅行のバスの点呼』 を思い出してごらん」

これまでのツール(xUnit / NUnit):

  • 実行時リフレクション
    これは 『出発直前の手動点呼』 だ。バスが出発するぞ(実行ボタン ON)となってから、先生がわざわざ座席を回って「佐藤くんいるかー? 鈴木さんいるかー?」と一人ひとり確認する。だから全員確認するまで時間がかかるし、たまに見落としもある。

先輩:「でも、TUnitのSource Generatorは、『駅の自動改札機』 なんだ」

TUnit:

  • コンパイル時 Source Generator
    君がコードを書いて(駅に入って)改札を通った瞬間に、「ピッ! 入場!」 と自動的にシステムに登録される。だから、バスが出発する(実行ボタンを押す)頃には、もう乗客名簿は完成しているんだ。

2-4.png

後輩:「なるほど! 『よーし、今から探すぞ』じゃなくて、『書いた瞬間にもう登録済み』 なんですね。これが『コンパイル中に動く』ってことか……!」

先輩:「そう。裏側で勝手に『名簿(実行用コード)』を作っておいてくれるんだ。これが最新のコンパイラ技術の力だよ」

5. 検証の合言葉 Assert.That

先輩:「テストの中身で一番大事なのはここだ」

await Assert.That(result).IsEqualTo(3);

後輩:Assert.That……直訳すると『〜であることを断言する』ですね」

先輩:「そう。Visual Studioなら、Assert.That(result). と打った瞬間に、IsEqualTo(等しい)とか IsNotNull(空じゃない)とか、使える検証メソッドがズラッと候補に出てくるだろう?」

2-5.png

後輩:「はい! 自分で覚えなくても、選ぶだけで書けちゃいますね。これなら英語が苦手な僕でも間違えなくて済みそう!」

6. テスト実行! 緑色のランプを灯せ

先輩:「じゃあ、いよいよ実行だ。テストエクスプローラーの 『すべてのテストを実行』 ボタン(緑色の再生マーク)を押してごらん」

後輩:「(ポチッ)……うわっ、一瞬で終わりました! テストの横に 緑色のチェックマーク が付きました!」

先輩:「おめでとう。さらにコードの上を見てごらん。メソッドの上に小さな文字で CodeLens(コードレンズ) が出ているはずだ」

後輩:「あ! テストメソッドの上に緑色のチェックマークが付いて 『Test Passed』 と出ました! コードの中に直接結果が出るんですね」

2-6.png

先輩:「これで君は、『変更しても壊れていないことを、Visual Studio を見るだけで確認できる』 ようになったんだ。もうリリースのたび、神に祈る必要はないぞ」

後輩:「すごい……! 守られてる感がすごいです! これでもうバグなんて怖くないですね!」

先輩:「その意気だ。この 『緑色のランプ』 を常に灯し続けることが、開発者の精神安定にとって一番の薬になるからな。これからどんどんテストを書いて、その安心感を味わっていこう」

後輩:「はい! テストコード、書くのが楽しくなってきました!」

(第3回へ続く)

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?