8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

テスト駆動開発やってみた

Last updated at Posted at 2019-08-03

はじめに

私は、今までテスト駆動開発(TDD)をしらずにソフトウェア開発をしていました。
そして下記のような苦労がありました。

  • バグを直そうとしたら、ほかのバグを埋め込んでしまった。
  • どこにバグの原因があるかわからず、デバッグに長い時間をかけていた。
  • コードをきれいにしたくても既存の振る舞いが変わってないか手動テストするのが大変だった。

TDDを導入することで、下記のメリットを享受できます。

  • 安全なリファクタリングができるので、きれいで動くコードをかける。
  • 自動テスト可能なコードをかける。

本記事は、私がTDDを実践して、これらのメリットを実感できた記録です。

またテスト対象の課題としてFizz Buzzを選びました。
本記事で紹介する完全なコードは、 GitHub を参照してください。

開発環境

本記事で解説するコードは、下記の環境で開発しました。

OS
Windows 10
テスティングフレームワーク
NUnit 3.10.1
IDE
Visual Studio 2019
CI
Circle CI
VCS
Git, GitHub

テストファーストでFizz Buzzを実装していく

まずは、テストを書いてテストが失敗することを確認してから実装を書いていきます。
Fizz Buzzのような簡単なプログラムでもストイックに一つ一つテストケースを追加していきました。

テストコード
[Test]
public void _Fizzが取得できる()
{
    var i = FizzBuzz.GetNum();
    Assert.That(i.ElementAt(2), Is.EqualTo("Fizz"));
}

[Test]
public void _Buzzが取得できる()
{
    var i = FizzBuzz.GetNum();
    Assert.That(i.ElementAt(4), Is.EqualTo("Buzz"));
}
[Test]
public void _FizzBuzzが取得できる()
{
    var i = FizzBuzz.GetNum();
    Assert.That(i.ElementAt(14), Is.EqualTo("FizzBuzz"));
}

リファクタリング中にバグを発見

黄金の回転にしたがいテストがパスしてからリファクタリングをしようとしました。

リファクタリング前

まず下記のコードは、テストをパスしています。 
※ リファクタリングに関係のない部分は省略しています。

リファクタリング前
var i = 0;
while(i++<100)
{
  // Fizz Buzzの実装
}

リファクタリング後(失敗)

while より for のほうがわかりやすいと思い下記のように書き換えました。

間違ったコード
for(var i=0;i<100;i++) // 1から列挙しないといけないのに、0から列挙してしまってる。
{
  // Fizz Buzzの実装
}

簡単な書き換えだと思ったので振る舞いは変わらないと思いましたが、
テストを実行すると、テストが失敗したので変更したコードにバグがあることに即座に気づけました。

test_failed.png

リファクタリング後(成功)

リファクタリングが成功したコード
for(var i=1;i<=100;i++)
{
  // Fizz Buzzの実装
}

再度、テストを実行してバグが修正されたことを確認できました。

test_passed.png

CIでのビルド

ローカルでテストを実行した結果は、オールグリーンでしたが、GitHubにプッシュしたところCIでのビルドが失敗してしまいました。

CircleCIでビルド失敗を検出

原因を調べたところ、メソッド名で、ひらがなや漢字を使っているにも関わらず、UTF-8ではなく Shift-JISで保存されていることが原因でした。
このようにローカルの環境だけでは、わからない問題も、CIで検知できました。

実行可能形式にする

テストコードから、Fizz Buzzの仕様を満たしていることを確認できたので、実行可能なコードを追加して完成です。

エントリポイント
static void Main(string[] args)
{
    foreach(var i in FizzBuzz.GetNum())
    {
        Console.WriteLine(i);
    }
}

もし、テストファーストをせず最初から実行可能にしていたら副作用によりテストできないコードになっていたことでしょう。

まとめ

私は、自分が思っているほど完璧ではなくミスをしてしまうということを改めて実感しました。
Fizz Buzzという単純な課題においても、TDDとCIの有用性を示せたと思います。

参考にした情報

8
7
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
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?