目的

とりあえず、とにかく、テストを書き、PHPUnit で実行すること。

想定される読者

  • PHP5 の基本的な文法を理解している
  • テスト駆動開発 (Test Driven Development; TDD) という言葉は知っているが、やってみたことは無い
  • PHPUnit 3.4 以降をインストールしている

TDD を知らない、PHPUnit をまだインストールしていない、という方は前回の記事『#01 インストール編』をご覧ください。

逆に、上記項目より上を行く方にとっては、特に参考になることは無いかもしれません。

テストされるコード

初めに、実際にプログラム上で使われるコードを用意します。

TDD の世界には「テストファースト」という言葉があります。それは、「実際のコードよりもテストコードを先に書く」というスタイルを表していますが、ここではそういった細かいことは気にせず話を進めます。

2 つの引数を足し算するだけの簡単なメソッドを持った、非常にシンプルなクラスです。

テストするコード

以下のようなコードを用意します。

これが、PHPUnit でテストを書く際の最小単位である、テストケースです。

注目すべきは、testAdd メソッドの中身です。これは、assertEquals というメソッドが、「$calc オブジェクトの add メソッドに、引数として 1 と 1 を渡せば、2 になるよね」といったことを確かめるためのコードです。

その他の部分は、PHPUnit でテストケースを書くためのおまじないみたいなものです。細かいルールについては次回以降、徐々に説明するとして、とりあえず次に進みます。

テストを実行する

ターミナル上で以下のコマンドを実行します。

$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

.

Time: 1 second, Memory: 4.75Mb

OK (1 test, 1 assertion)

最後の行の「OK」は、このテストが成功し、コード (Calc.php) が正確に実装されていることを示しています。また、1 つのテスト (1 test) と 1 つのアサーション (1 assertion) が実行された、ということも示されています。

もし add メソッドに間違いがあった場合は、PHPUnit の実行結果は以下のようになります。

$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 4.75Mb

There was 1 failure:

1) CalcTest::testAdd
Failed asserting that <integer:1> matches expected <integer:2>.

/path/to/CalcTest.php:10

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

これは、add メソッドが 2 を返すはずなのに、実際は 1 が返ってきてしまったために、テストが失敗してしまったことを示しています。

このような場合は、テストが成功するまでコードを修正しましょう。

アサーションとは

アサーションとは、変数の値や、メソッドの返り値をチェックすることです。さっきのテストケースでいえば、assertEquals メソッドがそれを行っています。

ざっくり言ってしまえば、前回からの繰り返しになりますが、「このメソッドにこの引数を与えると、この値が返ってくるよね」といったことをチェックすること、と言えるでしょう。

アサーションには多くの種類があり、例を挙げれば、

  • assertEquals()
    2 つの値が等しいか
  • assertTrue()
    値が true であるか
  • assertFalse()
    値が false であるか
  • assertType()
    値の型が正しいか

などなど、たくさんあります。

ですが、とりあえずは assertEquals と assertTrue だけ使えれば大抵のことは何とかなるので、他は必要に応じて調べながら覚えていけばよいでしょう。

まとめ

今回は、テストを書くこと、そして実行すること、に的を絞って解説しました。

次回は、テストコードを拡張させながら、PHPUnit でテストを書く際のルールについて、もう少し踏み込んでいこうとおもいます。

, ,

テスト駆動開発とは

テスト駆動開発 (Test Driven Development; TDD) とは、テストケースを書くことからプログラミングを始める、開発手法です。

ざっくり言うと、「このメソッドにこの引数を与えると、この値が返ってくるよね」といったことを、テストコードを用いて検証しながら、開発を進めていくスタイルと言うことができるでしょう。

TDD を知らない人がこの説明を聞くと、「TDD はコードの安全性のための手法である」と思われるかもしれません。
確かに、TDD はコードの安全性をもたらします。
しかし、TDD がもたらすものの中には、「コードの簡潔性」をも含まれます。

何故コードが簡潔になるのか

これは私見ですが、簡潔で読みやすいコードは、「入力と出力の束である」ことが多いです。
それはつまり、メソッド・関数が適切な単位で細かく文節され、それらの協調により組み立てられているコードです。

逆に読みづらい・わかりづらいコードは、「1 つのメソッド・関数が頑張り過ぎている」コードです。
1 つのメソッドが長いと、開発やデバッグの際に、「コード中のどこにバグが潜んでいるのか」を見つけ出すことが困難になります。

TDD による開発では、「テストしやすいコードを書く」ために、必然的に、コードが細分化されます。
その 1 つ 1 つに対して「このメソッドにこの引数を与えると、この値が返ってくるよね」を書いておけば、大幅なリファクタリングも、コードの同質性を検証しながら行うことができます。

TDD と私

新卒で Web エンジニアとして就職した 1 年前、私は TDD を知りませんでした。

そのうち、ブログなどで TDD について知り、Ruby の標準ライブラリ test/unit を使って、遊び程度にテストを書くようになります。

その後、東京 RubyKaigi 03 における、和田卓人氏 (@twada) のワークショップで RSpec の写経を行うことで、TDD の威力を実感することになります。

それ以来、仕事でも、PHPUnit を用いての、TDD による開発を心がけています。

プログラミングについては少しずつ勉強していますが、その中でも一番インパクトがあったのは間違いなく TDD であったと言いきることができます。
とはいえ、まだまったくの初心者レベルなので、勉強しながら、このブログで発表していこうと思います。

PHP Unit をインストール

Ubuntu 10.04 上の LAMP 環境で、PHP5 以上 (筆者は 5.3) 、そして pear がインストールされていることを前提としています。

公式ドキュメントに倣いますが、root 権限が必要となるため、sudo 付きで実行します。

sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com

上記コマンドで PEAR チャネル (ライブラリのインストール元のサーバ) を追加し、次のコマンドで PHPUnit がインストールされます。

sudo pear install phpunit/PHPUnit

これでインストール完了です。引数無しで phpunit コマンドを実行して、バージョン情報と Usage が表示されれば成功です。
2010 年 7 月 11 日現在では、PHPUnit 3.4.14 がインストールされます。

本日はここまで。
次回は実際にテストコードを書いていく予定です。

,