SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

C#で始めるテスト駆動開発入門

TDDBC大阪の課題をC#でやってみる ~ クラス設計とTDD

C#で始めるテスト駆動開発入門(5)

  • X ポスト
  • このエントリーをはてなブックマークに追加

自動販売機の概略

 粒度を小さくするために「自動販売機」クラスをさらに詳細にモデル化したいわけですが、幸いなことに自動販売機には実物があります。実際の自販機の構造は、だいたい次の図のようになっています。

飲み物自動販売機の概略
飲み物自動販売機の概略

 投入されたお金を勘定したり釣り銭を出したりするユニットは、コインメック(Coin Mechanism、硬貨用)やビルバリ(Bill Validator、紙幣用)と呼ばれています。商品ラックは複数のビンを持っていて、それぞれにジュースを格納しています。そして、それらの動きを制御するコントローラーがあります(実際のコントローラーは複数の基板に分かれています)。

 設計方針としては、コインメック(ビルバリの機能も含む)・商品ラック・コントローラーを個別に作り、最後に自動販売機として組み立てることにしましょう。

ステップ0 お金の投入と払い戻し

 これはコインメックだけの機能です。お題を見ていきましょう。

ステップ0 お金の投入と払い戻し


  1. 10円玉、50円玉、100円玉、500円玉、1000円札を1つずつ投入できる。
  2. 投入は複数回できる。
  3. 投入金額の総計を取得できる。
  4. 払い戻し操作を行うと、投入金額の総計を釣り銭として出力する。

 それでは、テストファーストしていきます。なお、製品コードとテストコードは別々のプロジェクトに分けます。製品コード側のAssemblyInfo.csにはInternalsVisibleTo属性を追加して、テストコード側から製品コード中のInternalなものにもアクセスできるようにしておきます。

製品コード側のAssemblyInfo.csにInternalsVisibleTo属性を追加
[assembly: InternalsVisibleTo("Tddbc大阪2Test")]
// "Tddbc大阪2Test"は、テストコードのアセンブリ名

ステップ0 1,3: コインメックにお金を1回だけ投入する

 課題文には「投入金額」という言葉が出てきますが、この金額はジュースを提供すると減ります。まだ代金として受け取ってはいないお金ということで、「預り金」と呼ぶことにします。

 まずは、10円玉を入れたら預り金が10円になる、という仮実装から始めましょう。ステップ0の1番目(の一部)と3番目をいっぺんにやります。

テストコード: 10円入れると、預り金が10円になる
[TestCase()]
public void お金を1回だけ投入するTest() {
  コインメック cm = new コインメック();
  cm.お金を投入する(10);

  Assert.AreEqual(10, cm.預り金);
}

 お金を投入する()コインメック預り金という状態が変化するわけですね。メソッド呼び出しの結果として状態が変化する場合は、このように状態の変化をアサートします。

 このテストケースを満たす仮実装は、次のようになります。

製品コード: コインメッククラス
internal class コインメック {

  public int 預り金 {
    get { return 10; } 
  }

  public void お金を投入する(int coin) {
  }
}

 テストコードをリファクタリングしてから、50円のテストケースを追加します。三角測量によって、お金を投入する()メソッドと預り金プロパティを完成させます。

テストコード: 50円入れると、預り金が50円になる
[TestCase(10, 10)]
[TestCase(50, 50)]  // ←追加
public void お金を1回だけ投入するTest(int 投入金, int 預り金の期待値) {
  コインメック cm = new コインメック();
  cm.お金を投入する(投入金);

  Assert.AreEqual(預り金の期待値, cm.預り金);
}
製品コード: コインメッククラス
private int _deposit;
public int 預り金 {
  get { return _deposit; }
  private set { _deposit = value; } 
}

public void お金を投入する(int coin) {
  預り金 = coin;
}

 なお、ここでは残りの金種(100円、500円、1000円)のテストケースを書いていません。なぜなら、それらのテストケースを追加しても、REDにできないからです。受け付ける金種については、ステップ1で実装することになります。

ステップ0 2,3: コインメックにお金を複数回投入する

 続けてお金を投入したら、その合計が預り金の額になるはずです。テストケースを1つ追加して、お金を投入する()メソッドを修正すれば完了です。

テストコード: 続けて投入すると、預り金がそれらの合計になる
[TestCase]
public void お金を複数回投入するTest() {
  コインメック cm = new コインメック();
  cm.お金を投入する(100);
  cm.お金を投入する(500);

  Assert.AreEqual(600, cm.預り金);
}
製品コード: コインメッククラス
public void お金を投入する(int coin) {
  預り金 += coin;
}

ステップ0 4: コインメックの払い戻し操作

 ステップ0の4番目は、お金を払い戻す()メソッドを実装します。投入した合計金額が返ってくるとともに、預り金は0にならなければいけません。

テストコード: お金を払い戻すと、預り金は0になる
[TestCase]
public void お金を払い戻すTest() {
  コインメック cm = new コインメック();
  cm.お金を投入する(1000);
  var 払戻金 = cm.お金を払い戻す();

  Assert.AreEqual(1000, 払戻金);
  Assert.AreEqual(0, cm.預り金);
}
製品コード: コインメッククラス
public int お金を払い戻す() {
  var 払戻金 = 預り金;
  預り金 = 0;
  return 払戻金;
}

次のページ
ステップ1 扱えないお金

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
C#で始めるテスト駆動開発入門連載記事一覧

もっと読む

この記事の著者

biac(ばいあっく)

HONDA R&Dで自動車の設計をやっていた機械屋さんが、技術の進化スピードに魅かれてプログラマーに。以来30年ほど、より良いコードをどうやったら作れるか、模索の人生。わんくま同盟の勉強会(名古屋)で、よく喋ってたりする。2014/10~2019/6 Microsoft MVP (Windows Devel...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6633 2012/06/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング