関西php勉強会のlimeの話

38
オブジェクト指向抜きで TDDしたいなら Limeを使うといいよ @tanakahisateru

Upload: hisateru-tanaka

Post on 27-Jun-2015

2.268 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: 関西Php勉強会のlimeの話

オブジェクト指向抜きでTDDしたいなら

Limeを使うといいよ

@tanakahisateru

Page 2: 関西Php勉強会のlimeの話

自己紹介

タナカヒサテル@tanakahisateru

PHPのフレームワークを開発しています

Pinoco https://github.com/tanakahisateru/pinoco

Page 3: 関西Php勉強会のlimeの話

Lime Testing Framework

Page 4: 関西Php勉強会のlimeの話

し…Symfonyだと!!

Page 5: 関西Php勉強会のlimeの話

大丈夫、Limeは単独で使えるから。しかも…

Page 6: 関西Php勉強会のlimeの話

超 簡 単

Page 7: 関西Php勉強会のlimeの話

ダウンロードhttp://trac.symfony-project.org/wiki/LimeTestingFramework

Page 8: 関西Php勉強会のlimeの話

ファイル1個だけ

Page 9: 関西Php勉強会のlimeの話

こんな感じ

Page 10: 関西Php勉強会のlimeの話

テストと実装を足すとこんな感じ

Page 11: 関西Php勉強会のlimeの話

テストの記述<?phprequire_once('lime.php');require_once('utils.php'); // これからテストするソース

$lime = new lime_test();

$zenkaku_tel = "06−6543−9876";$hankaku_tel = to_alphanum($zenkaku_tel);

$lime->is($hankaku_tel,"06-6543-9876");

utils-test.php

●単体ファイルをrequire_onceするだけで使えるようになる。●テストケースにclassもfunctionも書かなくていい。●assertEquals → is (短い)

Page 12: 関西Php勉強会のlimeの話

テストを実行$ php utils-test.php

1..2PHP Fatal error: Call to undefined function to_alphanum() in /Users/tanakahisateru/Desktop/limetest/utils-test.php on line 8

コマンドラインからutils-test.phpスクリプトを実行すると、失敗。to_alphnumメソッドが実装されていないことがわかる。

PHPでは「関数がない」とか「シンタックスエラーがある」という、コンパイラを通る言語なら普通起こらないようなミスが起こる。すべてのソースをいちどrequireして関数コールを試しておく。これコンパイルエラーのチェックと同じぐらい大事なこと。

Page 13: 関西Php勉強会のlimeの話

仮の実装<?phpfunction utils_to_alphanum($str){ return $str;}

utils.php

Page 14: 関西Php勉強会のlimeの話

テストの実行$ php utils-test.php

1..1not ok 1# Failed test (./utils-test.php at line 10)# got: '06−6543−9876'# expected: '06-6543-9876'# Looks like you failed 1 tests of 1.

もちろん失敗するよね。

Page 15: 関西Php勉強会のlimeの話

実装する<?phpfunction to_alphanum($str){ return str_replace( array( '0','1','2','3','4','5','6','7','8','9','−' ), array('0','1','2','3','4','5','6','7','8','9','-'), $str );}

utils.php

テスト駆動開発では、 「テストコードをクリアする最少の実装」を書くようにする。これポイント。最初から万能な実装を書いてしまうと、テストを成長させるモチベーションがなくなってしまう。

Page 16: 関西Php勉強会のlimeの話

テストの実行$ php utils-test.php

1..1ok 1# Looks like everything went fine.

$lime->is($hankaku_tel, "06-6543-9876"); というテストが期待通り動いた。

Page 17: 関西Php勉強会のlimeの話

テストケースの追加<?phprequire_once('lime.php');require_once('utils.php');

$lime = new lime_test();

$zenkaku_tel = "06−6543−9876";$hankaku_tel = to_alphanum($zenkaku_tel);$lime->is($hankaku_tel, "06-6543-9876");

$zenkaku_email = "tanakahisateru@gmail.com";$hankaku_email = to_alphanum($zenkaku_email);$lime->is($hankaku_email, "[email protected]");

Page 18: 関西Php勉強会のlimeの話

テストの実行$ php utils-test.php

1..1ok 1not ok 2# Failed test (./utils-test.php at line 13)# got: 'tanakahisateru@gmail.com'# expected: '[email protected]'# Looks like you planned 1 tests but ran 1 extra. # Looks like you failed 1 tests of 2.

もちろん新しく追加したテストは失敗する。

Page 19: 関西Php勉強会のlimeの話

で、実装する…の?<?phpfunction to_alphanum($str){ return str_replace( array( '0','1','2','3','4','5','6','7','8','9','−', 'a','b','c','d','e','f','g','h','i','j','k', 'l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','_','.','@' ), array( '0','1','2','3','4','5','6','7','8','9','-', 'a','b','c','d','e','f','g','h','i','j','k', 'l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','_','.','@' ), $str );}

utils.php

Page 20: 関西Php勉強会のlimeの話

まあテストは成功だけど$ php utils-test.php

ok 1ok 21..2# Looks like everything went fine.

この調子だと次のテストを書く気が起こらない。

Page 21: 関西Php勉強会のlimeの話

リファクタリングなど<?phpfunction to_alphanum($str){ return mb_convert_kana($str, 'a');}

utils.php

よし、書き換えよう。たぶんこの関数で同じ変換いけると思う。たぶん…

Page 22: 関西Php勉強会のlimeの話

おっとこれは!!

$ php utils-test.php

not ok 1# Failed test (./utils-test.php at line 9)# got: '06−6543−9876'# expected: '06-6543-9876'not ok 2# Failed test (./utils-test.php at line 13)# got: 'tanakahisateru@gmail.com'# expected: '[email protected]'1..2# Looks like you failed 2 tests of 2.

Page 23: 関西Php勉強会のlimeの話

やばいやばい忘れてた<?phpfunction to_alphanum($str, $encoding='utf-8'){ return mb_convert_kana($str, 'a', $encoding);}

Page 24: 関西Php勉強会のlimeの話

テストがあって良かった$ php utils-test.php

ok 1ok 21..2# Looks like everything went fine.

機能が劣化したらすぐにわかる。これほんとTDDのおいしさ。

Page 25: 関西Php勉強会のlimeの話

使い方はこちらで

http://www.symfony-project.org/gentle-introduction/1_4/ja/15-Unit-and-Functional-Testing

Page 26: 関西Php勉強会のlimeの話

と、まあこんなやりかたで

Page 27: 関西Php勉強会のlimeの話

PinocoはLimeでTDDしました

Page 28: 関西Php勉強会のlimeの話

Lime単体でTDDやってみて● コマンドラインのスクロール量がたいへん

● テスト項目が20個超え始めるときつい● テストスイートがない

● 回帰テストをまとめて一発でやりたい● 汚れたグローバル環境の再浄化が要る

● 実行スコープがグローバル● 連続して複数のテストを行うと前の状態に依存する● 続けてやったら単体テスト失敗するなどもってのほか

Page 29: 関西Php勉強会のlimeの話

というわけで作ったもの● Lime単体用のテストスイート● 複数のLimeテストをまとめて実行できる● 個々のテストは個別のPHPインタプリタで実行されるようにする

● OKの場合はいちいち報告しない

Page 30: 関西Php勉強会のlimeの話

ソースはこれだけ

Page 31: 関西Php勉強会のlimeの話

使い方

Page 32: 関西Php勉強会のlimeの話

実行した様子/Users/tanakahisateru/Sites/pinoco/test/unit/test_vars.php:# Pinoco_Vars Test# toArray test# import test1..47# Looks like everything went fine.

/Users/tanakahisateru/Sites/pinoco/test/unit/test_list.php:# Pinoco_List Test# push/pop# shift/unshift1..60# Looks like everything went fine.

/Users/tanakahisateru/Sites/pinoco/test/unit/test_lazy.php:# Pinoco_LazyValueProxy Test(略)

Page 33: 関西Php勉強会のlimeの話

それでも残る課題● 外部のシステムとの関係

● =単体テストにある本質的な問題● 言語ロジック外のシステムに依存すると、純粋な単体テストではなくなる。

● データ保存系のテストは次のテストの環境を書き換えてしまう。

● けれど自分の実装は実行の前提となる環境がないと動かせない、こまった。

Page 34: 関西Php勉強会のlimeの話

単体テストで重要な技術● モックオブジェクト

● 本番用と同じインターフェースの偽オブジェクト● オブジェクト指向的にいうとポリモーフィズム● 実際は何も書き換えないバージョンの外部環境● テスト可能な設計とは、モックオブジェクトを受け入れられるインターフェースだということ

● はいオブジェクト指向きましたね

Page 35: 関西Php勉強会のlimeの話

まあこういうことですよ

Symfony2でまさかの乗り換え… orz

Page 36: 関西Php勉強会のlimeの話

でも、

Page 37: 関西Php勉強会のlimeの話

PHP is not for OOP coders only.

そこまで突き詰めなくてもまずはTDDしよう。ユーザ層の幅広さ、それが「PHPらしさ」でしょ。

Page 38: 関西Php勉強会のlimeの話

詳しくはGitHubのPinocoのソースにて。

ありがとうございました。