Skip to content

開発研修 サーバサイドテスト

Kazuya Sato edited this page Feb 28, 2014 · 1 revision

自動ユニットテストの基礎

■目的

テスティングフレームワークのインストールと簡単なテストコードの記述をおこない、自動ユニットテストの基礎を学びます。 xUnit系、xSpec系の記述の違いについても簡単に触れます。

■課題1

数値の加算を行う簡単なプログラムがある。 RSpecおよびPHPUnitをインストールし、以下のことを検証するテストを記述してください。

  1. 1 + 2 = 3 となること
  2. 1 - 2 = -1 となること
  • 1 + (-2) であると考えてください
  1. 1 + 1.5 = 2.5 となること
class Adder
{
    public function add($x, $y)
    {
        return $x + $y;
    }
}
class Adder
  def add(x, y)
    x + y
  end
end

■課題2

テスティングフレームワークはxUnit系とxSpec系に大別できます。PHPUnitはxUnit系であり、RSpecはxSpec系です。 両者の違いを調べ、テストコードの可読性やメンテナンス性、テストのドキュメントとしての価値という観点から説明してください。 ヒント: 歴史的にはxUnit系のほうが古いので、主にxSpec系が台頭した理由を考えるという方向性で調べてみてください。

■課題3

作成したフォームに対し必要なテスト項目を考え、実際にテストを記述して下さい。

 

テストダブル

■目的

モックやスタブに代表されるテストダブルについて、その意味と用途を学びます。

■課題1

  • モック、スタブとはそれぞれ何か、調べて説明してください。
  • モックやスタブのように自動テストの実行を可能もしくは容易にすることを目的としてテスト対象の依存オブジェクトを別のオブジェクトに差し替えること、およびその差し替えたオブジェクトのことを「テストダブル」と呼びます。モック、スタブ以外のテストダブルにはどのようなものがあるか調べ、簡単に説明してください。

■課題2

以下のようなメッセージの送受信を行うプログラムのテストコードがあります。 このテストにおいて、モックを利用して振る舞いをテストした場合と、モックを利用せず状態をテストした場合の違いについて、以下に示す各々の変更可能性を考慮し説明してください。

  1. MessageSendersendメソッドの引数リストが変更された場合
  • exp.) 省略不可能の第三引数が必要になった
  1. MessageSendersendメソッドの内部実装がSMTPサーバに接続するように変更された場合
  2. MembersendMessageToメソッドで複雑な文面整形処理をするように変更になった場合

モックを利用してテストした場合(「メッセージが送信された」という振る舞いのテスト)

class MemberTest
{
    public function testSendMessage()
    {
        $sender = new Member();
        $receiver = new Member();

    	// MessageSenderのモックオブジェクトを生成し、
        // そのオブジェクトのsendメソッドが
        // 'テストメッセージ'という引数で1度だけコールされることを検証する
        $messageSenderMock = $this->getMock('MessageSender', array('send'));
        $messageSenderMock->expects($this->once())
                          ->method('send')
                          ->with($receiver->getMessageBox(), $this->equalTo('テストメッセージ'));
        $sender->setMessageSender = $messageSenderMock;

        $sender->sendMessageTo($receiver, "テストメッセージ");
    }
}

モックを利用せずにテストした場合(「メッセージが届いている」という状態のテスト)

class MemberTest
{
    public function testSendMessage()
    {
        $sender = new Member();
        $receiver = new Member();

        $sender->sendMessageTo($receiver, "テストメッセージ");

        $actual = $receiver->getLastMessage()->getBody();
        $this->assertEquals("テストメッセージ", $actual);
    }
}

 

テスト駆動開発(基礎編)

■目的

テスト駆動開発(TDD)の基礎を学びます。

■課題

TDDにおいて用いられる以下の用語について説明してください。

  • 仮実装
  • 三角測量
  • 明白な実装

テスト駆動開発(実践編)

■目的

簡単な課題に対してテスト駆動開発を実践し、その効果を実感してもらいます。

■課題

西暦年を表すクラスYearを任意のプログラミング言語で実装してください。 Yearは次のようなメソッドを持ちます。 ※以下のサンプルコードは Ruby で書かれていますが、同様の機能を提供できている限りにおいてメソッド名等は実装言語の文化/慣習にしたがってください。

class Year
  #
  # コンストラクタ
  #
  def initialize(year) # 西暦年を表す数字を渡す
    # TODO
  end

  #
  # うるう年かどうか
  #
  def leap_year?
    # TODO
  end

  #
  # 和暦の文字列形式
  #
  # exp.) year = Year.new(2014)
  #       year.to_jp_str # => "平成26年"
  def to_jp_str
    # TODO
  end
end

ただし、実装の際に以下のルールに【必ず】従うこと。

  • テストが成功しているとき(グリーン)には新しいプロダクトコードを追加してはいけない。ただし、テストが成功する状態を維持しながら内部実装のみを変更する(リファクタリング)ことは行ってもよい。
  • テストが失敗しているとき(レッド)にはできるだけ少ない実装かつ短い時間でそれを成功する状態にしなければいけない。
  • 次に示すタイミングでバージョン管理システムにコミットを生成する。なおその際コミットコメントに括弧内に示すプレフィックスをつけること。
  • 失敗するテストコードを書いたとき([Red])
  • 失敗したテストを最小の実装でパスするようにしたとき([Green])
  • テストを成功させた後でプロダクトコードを変更したとき([Refactoring])

■課題進行手順

  1. 与えられた課題の仕様について疑問や不明瞭な点を挙げてください。
  2. Gitのリポジトリを作成し、以下のファイルおよびディレクトリを作成してください。
  • todo.txt
  • prod/
  • test/
  1. todo.txtに1行に1つやるべきこと(以下、TODO)を書いてください。
  • TODO は1つあるいは少数のテストケースで表現できる程度まで細分化すること
  • この時点ですべての TODO を洗い出す必要はないので5〜10分ほど考えてみてある程度出たら次のステップに進むこと
  1. todo.txt のうち一つを選び、テストコードを書いてください。
  • todo.txt に記述した TODO と実際に実装する順番が同じである必要はありません。テストの書きやすそうな TODO を最初に選んでください。
  • このステップの終了時にコミットをしてください。
  1. 先述したルールに従って実装を進めてください。
  • 必要であれば任意のタイミングで todo.txt に TODO を追加して構いません。
Clone this wiki locally