SlideShare a Scribd company logo
EC-CUBE + PHPUnit で
 実践テスト駆動開発
         2010/6/26(土)
    有限会社Loop AZ 大河内健太郎
自己紹介
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日

•   FreeBSD / Mac OS X / Solaris 使ってます
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日

•   FreeBSD / Mac OS X / Solaris 使ってます

•   本業は Java のフレームワーク開発とか
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日

•   FreeBSD / Mac OS X / Solaris 使ってます

•   本業は Java のフレームワーク開発とか

•   Emacs23 のアイコン作りました
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日

•   FreeBSD / Mac OS X / Solaris 使ってます

•   本業は Java のフレームワーク開発とか

•   Emacs23 のアイコン作りました
自己紹介
•   名前: 大河内健太郎(id:nanasess) 年齢: 33才

•   出身: 愛知県

•   前職: 寿司屋の板前

•   資格: 調理師・ふぐ処理師

•   EC-CUBEとの出会いは初回リリース当日

•   FreeBSD / Mac OS X / Solaris 使ってます

•   本業は Java のフレームワーク開発とか

•   Emacs23 のアイコン作りました
PHPUnitとは
PHPUnitとは
• テスティングフレームワーク
PHPUnitとは
• テスティングフレームワーク
• テストプログラムを実行し確認するた
 めの仕組み
PHPUnitとは
• テスティングフレームワーク
• テストプログラムを実行し確認するた
 めの仕組み

• プログラマーの精神安定剤
PHPUnitとは
• テスティングフレームワーク
• テストプログラムを実行し確認するた
 めの仕組み

• プログラマーの精神安定剤
• レガシーコードをカイゼン
PHPUnitとは
• テスティングフレームワーク
• テストプログラムを実行し確認するた
 めの仕組み

• プログラマーの精神安定剤
• レガシーコードをカイゼン
• 変更の恐怖を開放して自信をつける
セットアップ
   •   前提

       •   cli 版の PHP がインストールされていること

       •   --with-pear で構築されていること

1. pear.phpunit.de を channel に追加
> pear channel-discover pear.phpunit.de

2. phpunit/PHPUnit をインストール
> pear install phpunit/PHPUnit


             参考: http://www.phpunit.de/manual/3.4/ja/installation.html
EC-CUBEで使うためには
   • EC-CUBE は SVN からチェックアウト
    • 2.4.4 からは同梱します!
   • EC-CUBE をインストールしておくこと
1. svn からチェックアウト
> svn checkout http://svn.ec-cube.net/open/tags/eccube-2.4.3

2. EC-CUBE をインストール
3. テストディレクトリへ移動
> cd eccube-2.4.3/test
TestSuite の実行

  • 動作に問題が無いか確認する
  • 必ず test ディレクトリから実行
TestSuite を実行
> phpunit TestSuite.php TestSuite
PHPUnit 3.4.14 by Sebastian Bergmann.

.....................

Time: 1 second, Memory: 12.50Mb

OK (21 tests, 24 assertions)
PHPUnit ことはじめ
PHPUnit ことはじめ
•   テンポが大事! 楽しく書こう!

    •   必ずしもテストファーストでなくて良い

•   メソッドベースとシナリオベース

•   実装コード以上に見やすく

•   サンプルコードの役割も果す

•   苦しいのは最初だけ. 書かなきゃずっと不安を
    抱える羽目に
PHPUnit の基本
PHPUnit の基本
•   テストメソッドは必ず test で始まる関数名をつける

•   assertEquals() などの関数で, 予想される結果と実際の結果を確認する

    •   結果が同じであればテスト成功) assertEquals(‘hoge’, ‘hoge’);

    •   結果が異なる場合はテスト失敗) assertEquals(‘hoge’, ‘boke’);

•   setUp() は必ず各テストメソッドの実行前に実行される

    •   データの前準備やトランザクションの開始

•   tearDown() は必ず各テストメソッドの実行後に実行される

    •   後処理やトランザクションのロールバック
テスト駆動開発1
テスト駆動開発1
•   EC-CUBE管理画面のテストを書いてみよう

•   まずは必ず成功する最小のテストを書く

•   実行してテストが成功することを確認する
テスト駆動開発1
    •   EC-CUBE管理画面のテストを書いてみよう

    •   まずは必ず成功する最小のテストを書く

    •   実行してテストが成功することを確認する


test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php

require_once("../html/require.php");
require_once("../data/class/pages/admin/design/LC_Page_Admin_Design_Expart.php");
require_once("PHPUnit/Framework.php");

class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase {

    function testInit() {
        // まずは必ず成功させる
        $this->assertEquals(true, true);
    }
}
テスト駆動開発2
テスト駆動開発2
• 更にテストを書いてテストが失敗する
 ことを確認する

• 何らかのバグで失敗するはずのテスト
 が成功してしまい, 気づかないのを防ぐ
 ため

• テスト成功と失敗を繰替えして開発を
 進める
テストの失敗を確認
data/class/page/admin/desigin/LC_Page_Admin_design_Expart.php

class LC_Page_Admin_Design_Expart extends LC_Page {

    function init() {
        // do nothing...
    }

    function process() {
        // do nothing...
    }
}
test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php

class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase {

    function setUp() {
        $this->objPage = new LC_Page_Admin_Design_Expart();
        $this->objPage->init();
    }

    function testInit() {
        $expected = “高度な設定”;
        $actual = $this->objPage->tpl_subtitle;
        // 失敗を確認
        $this->assertEquals($expected, $actual);
    }
}
テスト駆動開発3
テスト駆動開発3
•   細かくテストしながら本体のコードを仕上げてい
    く

•   テストが見にくくなったらリファクタリング

•   バグが見つかったら画面で確認する代わりにテス
    トを書く
test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php

class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase {

    function setUp() {
        $this->objPage = new LC_Page_Admin_Design_Expart();
        $this->objPage->init();
    }

    // 何をしているテストか解るように
    function testRegister() {
        $this->setParam(“サンプルデータ1”, “サンプルデータ2”);
        $this->argunment = “register 関数の引数”;
        $this->expected = “register 関数の予想する結果”;

        $this->scenario();
        $this->verify();
    }
    // DBへのテスト用データ投入処理など
    function setParam($value1, $value2) {
        // ...
    }
    // register 関数のサンプルコードになるように
    function scenario() {
        $this->actual = $this->objPage->register($this->argunment);
    }
    // 検証コードは共通化しやすい
    function verify() {
        $this->assertEquals($this->expected, $this->actual);
    }
}
Pageクラスのテスト
Pageクラスのテスト
•   インナークラスを使う

•   オーバーライドは積極的に

    •   認証や sendRedirect() はオーバーライド
        してしまおう

•   1テスト1フローで小さくテストすること
    を心掛ける
data/class/page/admin/desigin/LC_Page_Admin_design_Expart.php

class LC_Page_Admin_Design_Expart extends LC_Page {

    function process() {
        // 認証
        $this->authorization();

        switch ($_POST['mode']) {
        case "register":
            // 本番ではちゃんとエラーチェックすること
            $this->register($_POST['data']);
            $this->sendRedirect($this->getLocation(“/admin/index.php”));
            return;
            break;
        default:
        }
        // Smartyの assign
        $this->assignView();
    }

    function authorization() {
        SC_Utils_Ex::sfIsSuccess(new SC_Session());
    }

    function assignView() {
        $objView = new SC_AdminView();
        $objView->assignobj($this);
        $objView->display(MAIN_FRAME);
    }
}
test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php

class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase {

    function setUp() {
        $this->objPage = new LC_Page_Admin_Design_Expart_Mock();
        $this->objPage->init();
    }

    function testProcessBy登録時() {
        $_POST[‘mode’] = ‘register’;
        $_POST[‘data’] = ‘data’;

        $this->objPage->process();
        // 遷移先を確認
        $this->assertEquals(“http://example.jp/admin/index.php”,
                            $this->objPage->location);
    }
}
// ユーザー認証と Smarty の assign, sendRedirect はオーバーライドして遷移先の URL を確認
class LC_Page_Admin_Design_Expart_Mock extends LC_Page_Admin_Design_Expart {

    function authorization() {
        // quiet.
    }

    function assignView() {
        // quiet.
    }

    function sendRedirect($location) {
        $this->location = $location;
    }
}
美しく書くために
美しく書くために
•   テストメソッドにロジックは書かない

    •   scenario() や verify() を活用

•   テストが書きにくいと感じたらリファクタリン
    が必要な証拠

•   テストクラスは冗長に書く

•   why なコメントを積極的に書く

•   関数名に日本語使っちゃえ!

•   美しく書ければモチベーションアップ!
もっと活用
もっと活用
•   コードカバレッジ

    •   phpunit --coverege-html ./outputdir TestCase
•   継続的インテグレーション

    •   Maven
        •   http://maven.apache.org/
    •   hudson
        •   http://hudson-ci.org/
参考
• JUnit実践講座
 • http://www.objectclub.jp/community/
    memorial/homepage3.nifty.com/masarl/
    article/junit.html
• PHPUnitのマニュアル
 • http://www.phpunit.de/manual/3.4/ja/
宣伝
•   http://launchpad.net/xdo
    •   Java の JDO (Java Data Object - JSR243) を
        意識した O/R Mapper

    •   複雑に JOIN した SQL でも使える!

    •   EC-CUBE の次期バージョンに入れたい...

    •   鋭意開発中!
宣伝2

• 開発コミッター募集中!!
• EC-CUBE を一緒に開発しましょう!
• https://www.ec-cube.net/comitter/
  index.php
質疑応答
ご静聴ありがとう
ございました!

More Related Content

EC-CUBE + PHPUnit で 実践テスト駆動開発

  • 1. EC-CUBE + PHPUnit で 実践テスト駆動開発 2010/6/26(土) 有限会社Loop AZ 大河内健太郎
  • 3. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才
  • 4. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県
  • 5. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前
  • 6. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師
  • 7. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日
  • 8. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日 • FreeBSD / Mac OS X / Solaris 使ってます
  • 9. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日 • FreeBSD / Mac OS X / Solaris 使ってます • 本業は Java のフレームワーク開発とか
  • 10. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日 • FreeBSD / Mac OS X / Solaris 使ってます • 本業は Java のフレームワーク開発とか • Emacs23 のアイコン作りました
  • 11. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日 • FreeBSD / Mac OS X / Solaris 使ってます • 本業は Java のフレームワーク開発とか • Emacs23 のアイコン作りました
  • 12. 自己紹介 • 名前: 大河内健太郎(id:nanasess) 年齢: 33才 • 出身: 愛知県 • 前職: 寿司屋の板前 • 資格: 調理師・ふぐ処理師 • EC-CUBEとの出会いは初回リリース当日 • FreeBSD / Mac OS X / Solaris 使ってます • 本業は Java のフレームワーク開発とか • Emacs23 のアイコン作りました
  • 17. PHPUnitとは • テスティングフレームワーク • テストプログラムを実行し確認するた めの仕組み • プログラマーの精神安定剤 • レガシーコードをカイゼン
  • 18. PHPUnitとは • テスティングフレームワーク • テストプログラムを実行し確認するた めの仕組み • プログラマーの精神安定剤 • レガシーコードをカイゼン • 変更の恐怖を開放して自信をつける
  • 19. セットアップ • 前提 • cli 版の PHP がインストールされていること • --with-pear で構築されていること 1. pear.phpunit.de を channel に追加 > pear channel-discover pear.phpunit.de 2. phpunit/PHPUnit をインストール > pear install phpunit/PHPUnit 参考: http://www.phpunit.de/manual/3.4/ja/installation.html
  • 20. EC-CUBEで使うためには • EC-CUBE は SVN からチェックアウト • 2.4.4 からは同梱します! • EC-CUBE をインストールしておくこと 1. svn からチェックアウト > svn checkout http://svn.ec-cube.net/open/tags/eccube-2.4.3 2. EC-CUBE をインストール 3. テストディレクトリへ移動 > cd eccube-2.4.3/test
  • 21. TestSuite の実行 • 動作に問題が無いか確認する • 必ず test ディレクトリから実行 TestSuite を実行 > phpunit TestSuite.php TestSuite PHPUnit 3.4.14 by Sebastian Bergmann. ..................... Time: 1 second, Memory: 12.50Mb OK (21 tests, 24 assertions)
  • 23. PHPUnit ことはじめ • テンポが大事! 楽しく書こう! • 必ずしもテストファーストでなくて良い • メソッドベースとシナリオベース • 実装コード以上に見やすく • サンプルコードの役割も果す • 苦しいのは最初だけ. 書かなきゃずっと不安を 抱える羽目に
  • 25. PHPUnit の基本 • テストメソッドは必ず test で始まる関数名をつける • assertEquals() などの関数で, 予想される結果と実際の結果を確認する • 結果が同じであればテスト成功) assertEquals(‘hoge’, ‘hoge’); • 結果が異なる場合はテスト失敗) assertEquals(‘hoge’, ‘boke’); • setUp() は必ず各テストメソッドの実行前に実行される • データの前準備やトランザクションの開始 • tearDown() は必ず各テストメソッドの実行後に実行される • 後処理やトランザクションのロールバック
  • 27. テスト駆動開発1 • EC-CUBE管理画面のテストを書いてみよう • まずは必ず成功する最小のテストを書く • 実行してテストが成功することを確認する
  • 28. テスト駆動開発1 • EC-CUBE管理画面のテストを書いてみよう • まずは必ず成功する最小のテストを書く • 実行してテストが成功することを確認する test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php require_once("../html/require.php"); require_once("../data/class/pages/admin/design/LC_Page_Admin_Design_Expart.php"); require_once("PHPUnit/Framework.php"); class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase { function testInit() { // まずは必ず成功させる $this->assertEquals(true, true); } }
  • 30. テスト駆動開発2 • 更にテストを書いてテストが失敗する ことを確認する • 何らかのバグで失敗するはずのテスト が成功してしまい, 気づかないのを防ぐ ため • テスト成功と失敗を繰替えして開発を 進める
  • 31. テストの失敗を確認 data/class/page/admin/desigin/LC_Page_Admin_design_Expart.php class LC_Page_Admin_Design_Expart extends LC_Page { function init() { // do nothing... } function process() { // do nothing... } } test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase { function setUp() { $this->objPage = new LC_Page_Admin_Design_Expart(); $this->objPage->init(); } function testInit() { $expected = “高度な設定”; $actual = $this->objPage->tpl_subtitle; // 失敗を確認 $this->assertEquals($expected, $actual); } }
  • 33. テスト駆動開発3 • 細かくテストしながら本体のコードを仕上げてい く • テストが見にくくなったらリファクタリング • バグが見つかったら画面で確認する代わりにテス トを書く
  • 34. test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase { function setUp() { $this->objPage = new LC_Page_Admin_Design_Expart(); $this->objPage->init(); } // 何をしているテストか解るように function testRegister() { $this->setParam(“サンプルデータ1”, “サンプルデータ2”); $this->argunment = “register 関数の引数”; $this->expected = “register 関数の予想する結果”; $this->scenario(); $this->verify(); } // DBへのテスト用データ投入処理など function setParam($value1, $value2) { // ... } // register 関数のサンプルコードになるように function scenario() { $this->actual = $this->objPage->register($this->argunment); } // 検証コードは共通化しやすい function verify() { $this->assertEquals($this->expected, $this->actual); } }
  • 36. Pageクラスのテスト • インナークラスを使う • オーバーライドは積極的に • 認証や sendRedirect() はオーバーライド してしまおう • 1テスト1フローで小さくテストすること を心掛ける
  • 37. data/class/page/admin/desigin/LC_Page_Admin_design_Expart.php class LC_Page_Admin_Design_Expart extends LC_Page { function process() { // 認証 $this->authorization(); switch ($_POST['mode']) { case "register": // 本番ではちゃんとエラーチェックすること $this->register($_POST['data']); $this->sendRedirect($this->getLocation(“/admin/index.php”)); return; break; default: } // Smartyの assign $this->assignView(); } function authorization() { SC_Utils_Ex::sfIsSuccess(new SC_Session()); } function assignView() { $objView = new SC_AdminView(); $objView->assignobj($this); $objView->display(MAIN_FRAME); } }
  • 38. test/class/page/admin/desigin/LC_Page_Admin_design_Expart_Test.php class LC_Page_Admin_Design_Expart_Test extends PHPUnit_Framework_TestCase { function setUp() { $this->objPage = new LC_Page_Admin_Design_Expart_Mock(); $this->objPage->init(); } function testProcessBy登録時() { $_POST[‘mode’] = ‘register’; $_POST[‘data’] = ‘data’; $this->objPage->process(); // 遷移先を確認 $this->assertEquals(“http://example.jp/admin/index.php”, $this->objPage->location); } } // ユーザー認証と Smarty の assign, sendRedirect はオーバーライドして遷移先の URL を確認 class LC_Page_Admin_Design_Expart_Mock extends LC_Page_Admin_Design_Expart { function authorization() { // quiet. } function assignView() { // quiet. } function sendRedirect($location) { $this->location = $location; } }
  • 40. 美しく書くために • テストメソッドにロジックは書かない • scenario() や verify() を活用 • テストが書きにくいと感じたらリファクタリン が必要な証拠 • テストクラスは冗長に書く • why なコメントを積極的に書く • 関数名に日本語使っちゃえ! • 美しく書ければモチベーションアップ!
  • 42. もっと活用 • コードカバレッジ • phpunit --coverege-html ./outputdir TestCase • 継続的インテグレーション • Maven • http://maven.apache.org/ • hudson • http://hudson-ci.org/
  • 43. 参考 • JUnit実践講座 • http://www.objectclub.jp/community/ memorial/homepage3.nifty.com/masarl/ article/junit.html • PHPUnitのマニュアル • http://www.phpunit.de/manual/3.4/ja/
  • 44. 宣伝 • http://launchpad.net/xdo • Java の JDO (Java Data Object - JSR243) を 意識した O/R Mapper • 複雑に JOIN した SQL でも使える! • EC-CUBE の次期バージョンに入れたい... • 鋭意開発中!
  • 45. 宣伝2 • 開発コミッター募集中!! • EC-CUBE を一緒に開発しましょう! • https://www.ec-cube.net/comitter/ index.php

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n