「え?phpunit使ったことないとかマジすか!?」
って誰かに言われた気がするので急いで勉強開始。
(先日と同じ始まり方)
事の発端は、品質の確保について考えさせられたとき。
正直自分が書いたコードのテストって、あまりやる気でないじゃないですか。
他人の粗捜しはそんなに嫌いじゃないけど、自分のは嫌じゃないですか。
他人に、バグじゃねーか、って言われると殺意がわきますが
プログラムに怒られるなら問題なし。
だって、こいつらは僕の味方だもん、裏切らないもん。
実はTDDが主流だったころの産物で
時代はBDD用のphpSpecが主流らしい?
が、時代遅れの僕はまずphpunitから勉強を始めるのです。
新しいものは無条件でよいというわけではなく、
構想や求めるものが違うなら両方知っておいて使い分けるべき!
という事でさっそくやってみよう。
さっそくcomposerでインストールだ!
現時点ではVer6まで出てるみたいですが、PHP7以上なので
いまだにPHP5.6系から抜け出せない時代遅れの僕は 5でガマン。
でも、phpunit入門でググると 3系の記事がたくさんヒットする。
さらに書かれたのが2007年の記事とかです。
僕は10年前から現代に向かって全力疾走しているという事ですね!
公式の日本語ドキュメントを見つけたものの、いまいちわかりにくい。
サンプルコードはあるものの、
ディレクトリ構成とかテストを実行する手順とかが見当たらず。
幸いphpunit5の記事もみつけたので、
それに習って実験開始!
やはりSEはコードを書いてなんぼ。トライ&エラー万歳!
== 前提 ==
composerでインストールする
(composerはインストール済み)
== ディレクトリ構造 ==
c:\vhosts\phpunit <= テストに使うディレクトリ \classes <= 検証されるクラスの格納場所 \case <= 検証用のクラスの格納場所
実際は検証されるクラスの格納場所、なんていらんかもね。
既に存在していて絶対パスか何かで呼び出しそうだし。
1. まずは composer.json を書くよ
c:\vhosts\phpunit\composer.json というファイルを作って
↓の内容で保存
{ "name":"hogehoge/phpunittest", "config": { "platform":{ "php": "5.6.23" } }, "require": { "phpunit/phpunit": "*" } }
name のところは自分の好きな名前に変えてもいいし、無くしてもいい。
phpのところは自分のバージョンに合わせてね
phpのバージョンを書くと、それに合った中で一番新しいのがインストールされるみたい。
いい加減php7に移行しろよって話かもですが、いろいろ事情がねw
2. composer を使ってインストールだ
cd c:\vhosts\phpunit composer install
とコマンドを打ちます。
怒られたらcomposer.jsonを確認したり、php.iniを確認したり?
エラーメッセージは英語ですが、ちゃんとわかりやすく書いてるっぽいので
読むか、翻訳にかけてみましょう。
3. 検証されるクラスを書くよ
c:\vhosts\phpunit\classes\Hoge.php というファイルを作り
下の内容を書いて保存
入力された文字を大文字にそろえたり小文字にそろえたりするクラスです。
でも、バグがあります。
toKomojiにhoge を入れると hoge が返ってくるはずなのに、なぜかhage が返ってくるというバグです。
これは仕様ではなくバグです。
多分、会社が嫌になって辞める直前にありったけの悪意を叩き込んだのでしょう。
いい子のみんなは真似しないでね!
4. テストコードを書いてテストするよ その1
みなさん、お待ちかね!
やっとPhpUnitの出番だよ!
複数の検証用のファイルを一発で走らせるのが前提だと思うので
それっぽくするためにファイルを二つ作るつもりだけど
とりあえずはひとつだけ、テストが成功するパターンを書くよ
名前の規則はとりあえず二つあって
テスト用のクラス名とファイル名は一緒にしないとダメみたい。
っていうのと
テスト用の関数の名前は testなんとか にしないとダメみたい。
ってことらしい。
一つ目
c:\vhosts\phpunit\case\SuccessTest.php というファイルを作って下の内容で保存
obj = new Hoge(); } /** * 大文字変換のテスト */ public function testToOomoji() { $this->assertEquals('ABC', $this->obj->toOomoji('abc')); $this->assertEquals('ABC', $this->obj->toOomoji('ABC')); $this->assertEquals('ABC', $this->obj->toOomoji('abC')); } /** * 小文字変換のテスト */ public function testToKomoji() { $this->assertEquals('abc', $this->obj->toKomoji('abc')); $this->assertEquals('abc', $this->obj->toKomoji('ABC')); $this->assertEquals('abc', $this->obj->toKomoji('abC')); } } ?>
保存ができたら
下のコマンドを打って実際にテストだ!
c:\vhosts\phpunit\vendor\bin\phpunit c:\vhosts\phpunit\case\SuccessTest.php
コマンドが長いのは パスを通したり cdで移動したりすれば解決するかもだけど
そういう設定は自分で考えて使いやすく調整してほしい。
ちゃんと動いてれば
c:\vhosts\phpunit>c:\vhosts\phpunit\vendor\bin\phpunit c:\vhosts\phpunit\case\SuccessTest.php PHPUnit 5.7.22 by Sebastian Bergmann and contributors. .. 2 / 2 (100%) Time: 71 ms, Memory: 2.00MB OK (2 tests, 6 assertions)
↑こんな感じで表示されると思う。
5. テストコードを書いてテストするよ その2
んじゃ次はさっきの悪意のあるコードを偶然にも踏むテストを書いてみるよ!
こうして早期発見したバグの犯人はきっとアイツだ!
c:\vhosts\phpunit\case\FailureTest.php というファイルを作って下の内容で保存
obj = new Hoge(); } /** * 大文字変換のテスト */ public function testToOomoji() { $this->assertEquals('HOGE', $this->obj->toOomoji('hoge')); $this->assertEquals('HOGE', $this->obj->toOomoji('HOGE')); $this->assertEquals('HOGE', $this->obj->toOomoji('hoGE')); } /** * 小文字変換のテスト */ public function testToKomoji() { $this->assertEquals('hoge', $this->obj->toKomoji('hoge')); $this->assertEquals('hoge', $this->obj->toKomoji('HOGE')); $this->assertEquals('hoge', $this->obj->toKomoji('hoGE')); } } ?>
そしたらテストだ!
せっかくなので今回は 4. で作った SuccessTest.php も一緒にテスト
というか、ディレクトリに入ってるものまとめてテストするよ
前回ファイル名だってところをディレクトリ名にしてやればいいだけ、簡単だね!
c:\vhosts\phpunit\vendor\bin\phpunit c:\vhosts\phpunit\case
今回の結果は・・・
c:\vhosts\phpunit>c:\vhosts\phpunit\vendor\bin\phpunit c:\vhosts\phpunit\case PHPUnit 5.7.22 by Sebastian Bergmann and contributors. .F.. 4 / 4 (100%) Time: 84 ms, Memory: 2.50MB There was 1 failure: 1) FailureTest::testToKomoji Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'hoge' +'hage' C:\vhosts\phpunit\case\FailureTest.php:33 FAILURES! Tests: 4, Assertions: 10, Failures: 1.
こんな感じ!
エラーだって事も、どんなエラーかってのもなんとなく雰囲気でわかると思う。
ホントは英語勉強した方がいいんだろうね。orz
6. じゃあついでだからバグ直してみようか。
5のテスト結果を見ると
FailureTest.phpの33行目に書いてあるテストで
hogeが返ってくるべき関数でhageが返ってきたよ
というのがわかるので
まず33行目を抜粋↓
$this->assertEquals('hage', $this->obj->toKomoji('hoge'));
objはHogeクラスなので Hoge->toKomiji() がおかしいぞ、と推理を働かせて関数の中身を見てみる
function toKomoji($str){ if($str =='hoge')return 'hage'; return strToLower($str); }
そして気が付く、なんだこれ!?
function toKomoji($str){ if($str =='hoge')return 'hage'; //<=なんだコレ!? return strToLower($str); }
なんだコレ!?なコードの行を消してから再度テストすると
c:\vhosts\phpunit>c:\vhosts\phpunit\vendor\bin\phpunit c:\vhosts\phpunit\case PHPUnit 5.7.22 by Sebastian Bergmann and contributors. .... 4 / 4 (100%) Time: 70 ms, Memory: 2.25MB OK (4 tests, 12 assertions)
無事にバグが無くなり
それは、つい先日失踪したKさんの野望は潰えたことを意味する。
尚、無能な営業はKさんに電話をしたが既に不通となっていた。
同僚は恨むでもなく、ただKさんの幸せを願うのであった。
と、まぁこんな感じで使うらしい。
でも、あくまで基本。
いろんなテストデータの用意の仕方とかいろいろあるので
もっと勉強して使いこなすべし、って感じですね。
今日はこの辺で。