Source for file UnitTestManager.php

Documentation is available at UnitTestManager.php

  1. <?php
  2. /**
  3.  *  UnitTestManager.php
  4.  *
  5.  *  @author     Takuya Ookubo <sfio@sakura.ai.to>
  6.  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
  7.  *  @package    Ethna
  8.  *  @version    $Id: 2611104a545dcfa3cb7485d66a1d541e4ce64020 $
  9.  */
  10.  
  11. require_once 'simpletest/unit_tester.php';
  12. require_once 'UnitTestCase.php';
  13. require_once 'UnitTestReporter.php';
  14.  
  15. /**
  16.  *  Ethnaユニットテストマネージャクラス
  17.  *
  18.  *  @author     Takuya Ookubo <sfio@sakura.ai.to>
  19.  *  @access     public
  20.  *  @package    Ethna
  21.  */
  22. {
  23.     /** @var    object  Ethna_Controller    コントローラオブジェクト */
  24.     var $ctl;
  25.  
  26.     /** @var    array                       一般テストケース定義 */
  27.     var $testcase = array();
  28.  
  29.     /**
  30.      *  Ethna_UnitTestManagerのコンストラクタ
  31.      *
  32.      *  @access public
  33.      *  @param  object  Ethna_Backend   $backend   Ethna_Backendオブジェクト
  34.      */
  35.     public function __construct($backend)
  36.     {
  37.         parent::__construct($backend);
  38.         $this->ctl = Ethna_Controller::getInstance();
  39.         $this->class_factory $this->ctl->getClassFactory();
  40.         $this->testcase = array_merge($this->testcase$this->_getTestCaseList());
  41.     }
  42.  
  43.     /**
  44.      *  action, view 以外のテストケースの一覧を取得する
  45.      *
  46.      *  @access private
  47.      *  @param  テストケースが含まれているディレクトリ名 
  48.      */
  49.     function _getTestCaseList($test_dir NULL)
  50.     {
  51.         $r array();
  52.  
  53.         if (is_null($test_dir)) {
  54.             $test_dir $this->ctl->getTestdir();
  55.         }
  56.         $base $this->ctl->getBasedir();
  57.  
  58.         //  テストディレクトリはユーザが変更できる
  59.         //  ため、実行時の変更のタイミング次第では
  60.         //  WARNING が出る可能性があるのをケアする
  61.         if (!is_dir($test_dir)) {
  62.             return array();
  63.         }
  64.  
  65.         $child_dir_list array();
  66.  
  67.         $dh opendir($test_dir);
  68.         if ($dh == false{
  69.             return;
  70.         }
  71.  
  72.         $ext $this->ctl->getExt('php');
  73.         while (($file readdir($dh)) !== false{
  74.             if ($file == "." || $file == ".."{
  75.                 continue;
  76.             }
  77.             $file $test_dir $file;
  78.  
  79.             if (is_dir($file)) {
  80.                 $child_dir_list[$file;
  81.                 continue;
  82.             }
  83.  
  84.             if (preg_match("/\.$ext\$/"$file== 0{
  85.                 continue;
  86.             }
  87.  
  88.             $file str_replace($this->ctl->getTestdir()''$file);
  89.  
  90.             $key ereg_replace("^(.*)Test\.$ext"'\1'$file);
  91.             $key str_replace('/'''$key);
  92.  
  93.             $r[$keystr_replace($base '/'''$this->ctl->getTestdir($file);
  94.         }
  95.  
  96.         closedir($dh);
  97.  
  98.         foreach ($child_dir_list as $child_dir{
  99.             $tmp $this->_getTestCaseList($child_dir "/");
  100.             $r array_merge($r$tmp);
  101.         }
  102.  
  103.         return $r;
  104.     }
  105.  
  106.     /**
  107.      *  定義済みアクション一覧を取得する
  108.      *
  109.      *  @access public
  110.      *  @return array   アクション一覧
  111.      */
  112.     function _getActionList()
  113.     {
  114.         $im new Ethna_InfoManager($this->backend);
  115.         return $im->getActionList();
  116.     }
  117.  
  118.     /**
  119.      *  クラス名からビュー名を取得する
  120.      *
  121.      *  @access public
  122.      *  @param  string  $class_name     ビュークラス名
  123.      *  @return string  アクション名
  124.      */
  125.     function viewClassToName($class_name)
  126.     {
  127.         $prefix sprintf("%s_View_"$this->ctl->getAppId());
  128.         if (preg_match("/$prefix(.*)/"$class_name$match== 0{
  129.             // 不明なクラス名
  130.             return null;
  131.         }
  132.         $target $match[1];
  133.  
  134.         $action_name substr(preg_replace('/([A-Z])/e'"'_' . strtolower('\$1')"$target)1);
  135.  
  136.         return $action_name;
  137.     }
  138.  
  139.     /**
  140.      *  指定されたクラス名を継承しているかどうかを返す
  141.      *
  142.      *  @access private
  143.      *  @param  string  $class_name     チェック対象のクラス名
  144.      *  @param  string  $parent_name    親クラス名
  145.      *  @return bool    true:継承している false:いない
  146.      */
  147.     function _isSubclassOf($class_name$parent_name)
  148.     {
  149.         while ($tmp get_parent_class($class_name)) {
  150.             if (strcasecmp($tmp$parent_name== 0{
  151.                 return true;
  152.             }
  153.             $class_name $tmp;
  154.         }
  155.         return false;
  156.     }
  157.  
  158.     /**
  159.      *  ビュースクリプトを解析する
  160.      *
  161.      *  @access private
  162.      *  @param  string  $script ファイル名
  163.      *  @return array   ビュークラス定義一覧
  164.      */
  165.     function __analyzeViewScript($script)
  166.     {
  167.         $class_list array();
  168.  
  169.         $source "";
  170.         $fp fopen($script'r');
  171.         if ($fp == false{
  172.             return null;
  173.         }
  174.         while (feof($fp== false{
  175.             $source .= fgets($fp8192);
  176.         }
  177.         fclose($fp);
  178.  
  179.         // トークンに分割してクラス定義情報を取得
  180.         $token_list token_get_all($source);
  181.         for ($i 0$i count($token_list)$i++{
  182.             $token $token_list[$i];
  183.  
  184.             if ($token[0== T_CLASS{
  185.                 // クラス定義開始
  186.                 $i += 2;
  187.                 $class_name $token_list[$i][1];       // should be T_STRING
  188.                 if ($this->_isSubclassOf($class_name'Ethna_ViewClass')) {
  189.                     $view_name $this->viewClassToName($class_name);
  190.                     $class_list[$view_namearray(
  191.                         'template_file' => $this->ctl->_getForwardPath($view_name),
  192.                         'view_class' => $class_name,
  193.                         'view_class_file' => $this->ctl->getDefaultViewPath($view_name),
  194.                     );
  195.                 }
  196.             }
  197.         }
  198.  
  199.         if (count($class_list== 0{
  200.             return null;
  201.         }
  202.         return $class_list;
  203.     }
  204.  
  205.     /**
  206.      *  ディレクトリ以下のビュースクリプトを解析する
  207.      *
  208.      *  @access private
  209.      *  @param  string  $action_dir     解析対象のディレクトリ
  210.      *  @return array   ビュークラス定義一覧
  211.      */
  212.     function __analyzeViewList($view_dir null)
  213.     {
  214.         $r array();
  215.  
  216.         if (is_null($view_dir)) {
  217.             $view_dir $this->ctl->getViewdir();
  218.         }
  219.         $prefix_len strlen($this->ctl->getViewdir());
  220.  
  221.         $ext '.' $this->ctl->getExt('php');
  222.         $ext_len strlen($ext);
  223.  
  224.         $dh opendir($view_dir);
  225.         if ($dh{
  226.             while (($file readdir($dh)) !== false{
  227.                 $path "$view_dir/$file";
  228.                 if ($file != '.' && $file != '..' && is_dir($path)) {
  229.                     $tmp $this->__analyzeViewList($path);
  230.                     $r array_merge($r$tmp);
  231.                     continue;
  232.                 }
  233.                 if (substr($file-$ext_len$ext_len!= $ext{
  234.                     continue;
  235.                 }
  236.  
  237.                 include_once($path);
  238.                 $class_list $this->__analyzeViewScript($path);
  239.                 if (is_null($class_list== false{
  240.                     $r array_merge($r$class_list);
  241.                 }
  242.             }
  243.         }
  244.         closedir($dh);
  245.  
  246.         return $r;
  247.     }
  248.  
  249.     /**
  250.      *  定義済みビュー一覧を取得する
  251.      *
  252.      *  @access public
  253.      *  @return array   ビュー一覧
  254.      */
  255.     function _getViewList()
  256.     {
  257.         $im new Ethna_InfoManager($this->backend);
  258.         //$view_class_list = array_keys($im->getForwardList());
  259.  
  260.         $r array();
  261.  
  262.         // テンプレート/ビュースクリプトを解析する
  263.         $forward_list $im->_analyzeForwardList();
  264.         $view_list $this->__analyzeViewList();
  265.  
  266.         // ビュー定義エントリ一覧
  267.         $manifest_forward_list $im->_getForwardList_Manifest($forward_list);
  268.  
  269.         // ビュー定義省略エントリ一覧
  270.         $implicit_forward_list $im->_getForwardList_Implicit($forward_list$manifest_forward_list);
  271.  
  272.         $r array_merge($view_list$manifest_forward_list$implicit_forward_list);
  273.         ksort($r);
  274.  
  275.         return $r;
  276.     }
  277.  
  278.     /**
  279.      *  アクションテストクラスを取得する
  280.      *
  281.      *  @access private
  282.      *  @return array 
  283.      */
  284.     function _getTestAction()
  285.     {
  286.         $action_class_list array_keys($this->_getActionList());
  287.  
  288.         // テストの存在するアクション
  289.         foreach ($action_class_list as $key => $action_name{
  290.             $action_class $this->ctl->getDefaultActionClass($action_namefalse).'_TestCase';
  291.             if (!class_exists($action_class)) {
  292.                 unset($action_class_list[$key]);
  293.             }
  294.         }
  295.  
  296.         return $action_class_list;
  297.     }
  298.  
  299.     /**
  300.      *  ビューテストクラスを取得する
  301.      *
  302.      *  @access private
  303.      *  @return array 
  304.      */
  305.     function _getTestView()
  306.     {
  307.         $view_class_list array_keys($this->_getViewList());
  308.  
  309.         // テストの存在するビュー
  310.         foreach ($view_class_list as $key => $view_name{
  311.             $view_class $this->ctl->getDefaultViewClass($view_namefalse).'_TestCase';
  312.             if (!class_exists($view_class)) {
  313.                 unset($view_class_list[$key]);
  314.             }
  315.         }
  316.  
  317.         return $view_class_list;
  318.     }
  319.  
  320.     /**
  321.      *  ユニットテストを実行する
  322.      *
  323.      *  @access private
  324.      *  @return mixed   0:正常終了 Ethna_Error:エラー
  325.      */
  326.     function run()
  327.     {
  328.         $action_class_list $this->_getTestAction();
  329.         $view_class_list $this->_getTestView();
  330.  
  331.         $test new GroupTest("Ethna UnitTest");
  332.  
  333.         // アクション
  334.         foreach ($action_class_list as $action_name{
  335.             $action_class $this->ctl->getDefaultActionClass($action_namefalse).'_TestCase';
  336.             $action_form $this->ctl->getDefaultFormClass($action_namefalse).'_TestCase';
  337.  
  338.             $test->addTestCase(new $action_class($this->ctl));
  339.             $test->addTestCase(new $action_form($this->ctl));
  340.         }
  341.  
  342.         // ビュー
  343.         foreach ($view_class_list as $view_name{
  344.             $view_class $this->ctl->getDefaultViewClass($view_namefalse).'_TestCase';
  345.  
  346.             $test->addTestCase(new $view_class($this->ctl));
  347.         }
  348.  
  349.         // 一般
  350.         foreach ($this->testcase as $class_name => $file_name{
  351.             $dir $this->ctl->getBasedir().'/';
  352.             include_once $dir $file_name;
  353.             $testcase_name $class_name.'_TestCase';
  354.             $test->addTestCase(new $testcase_name($this->ctl));
  355.         }
  356.  
  357.         // ActionFormのバックアップ
  358.         $af $this->ctl->getActionForm();
  359.  
  360.         //出力したい形式にあわせて切り替える
  361.         $cli_enc $this->ctl->getClientEncoding();
  362.         $reporter new Ethna_UnitTestReporter($cli_enc);
  363.         $test->run($reporter);
  364.  
  365.         // ActionFormのリストア
  366.         $this->ctl->setActionForm($af);
  367.         $this->backend->setActionForm($af);
  368.  
  369.         return array($reporter->report$reporter->result);
  370.     }
  371. }

Documentation generated on Fri, 11 Nov 2011 03:59:13 +0900 by phpDocumentor 1.4.3