3 * Ethna_UnitTestManager.php
5 * @author Takuya Ookubo <sfio@sakura.ai.to>
6 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
11 require_once('simpletest/unit_tester.php');
12 require_once('Ethna_UnitTestCase.php');
13 require_once('Ethna_UnitTestReporter.php');
16 * Ethnaユニットテストマネージャクラス
18 * @author Takuya Ookubo <sfio@sakura.ai.to>
22 class Ethna_UnitTestManager extends Ethna_AppManager
24 /** @var object Ethna_Controller コントローラオブジェクト */
27 /** @var array 一般テストケース定義 */
28 var $testcase = array();
31 * Ethna_UnitTestManagerのコンストラクタ
34 * @param object Ethna_Backend &$backend Ethna_Backendオブジェクト
36 function Ethna_UnitTestManager(&$backend)
38 parent::Ethna_AppManager($backend);
39 $this->ctl =& Ethna_Controller::getInstance();
40 $this->class_factory =& $this->ctl->getClassFactory();
41 $this->testcase = array_merge($this->testcase, $this->_getTestCaseList());
45 * action, view 以外のテストケースの一覧を取得する
48 * @param テストケースが含まれているディレクトリ名
50 function _getTestCaseList($test_dir = NULL)
54 if (is_null($test_dir)) {
55 $test_dir = $this->ctl->getTestdir();
57 $base = $this->ctl->getBasedir();
59 $child_dir_list = array();
61 $dh = opendir($test_dir);
66 $ext = $this->ctl->getExt('php');
67 while (($file = readdir($dh)) !== false) {
68 if ($file == "." || $file == "..") {
71 $file = $test_dir . $file;
74 $child_dir_list[] = $file;
78 if (preg_match("/\.$ext\$/", $file) == 0) {
82 $file = str_replace($this->ctl->getTestdir(), '', $file);
84 $key = ereg_replace("^(.*)Test\.$ext", '\1', $file);
85 $key = str_replace('/', '', $key);
87 $r[$key] = str_replace($base . '/', '', $this->ctl->getTestdir() . $file);
92 foreach ($child_dir_list as $child_dir) {
93 $tmp = $this->_getTestCaseList($child_dir . "/");
94 $r = array_merge($r, $tmp);
104 * @return array アクション一覧
106 function _getActionList()
108 $im =& new Ethna_InfoManager($this->backend);
109 return $im->getActionList();
116 * @param string $class_name ビュークラス名
117 * @return string アクション名
119 function viewClassToName($class_name)
121 $prefix = sprintf("%s_View_", $this->ctl->getAppId());
122 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
128 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
134 * 指定されたクラス名を継承しているかどうかを返す
137 * @param string $class_name チェック対象のクラス名
138 * @param string $parent_name 親クラス名
139 * @return bool true:継承している false:いない
141 function _isSubclassOf($class_name, $parent_name)
143 while ($tmp = get_parent_class($class_name)) {
144 if (strcasecmp($tmp, $parent_name) == 0) {
156 * @param string $script ファイル名
157 * @return array ビュークラス定義一覧
159 function __analyzeViewScript($script)
161 $class_list = array();
164 $fp = fopen($script, 'r');
168 while (feof($fp) == false) {
169 $source .= fgets($fp, 8192);
173 // トークンに分割してクラス定義情報を取得
174 $token_list = token_get_all($source);
175 for ($i = 0; $i < count($token_list); $i++) {
176 $token = $token_list[$i];
178 if ($token[0] == T_CLASS) {
181 $class_name = $token_list[$i][1]; // should be T_STRING
182 if ($this->_isSubclassOf($class_name, 'Ethna_ViewClass')) {
183 $view_name = $this->viewClassToName($class_name);
184 $class_list[$view_name] = array(
185 'template_file' => $this->ctl->_getForwardPath($view_name),
186 'view_class' => $class_name,
187 'view_class_file' => $this->ctl->getDefaultViewPath($view_name),
193 if (count($class_list) == 0) {
200 * ディレクトリ以下のビュースクリプトを解析する
203 * @param string $action_dir 解析対象のディレクトリ
204 * @return array ビュークラス定義一覧
206 function __analyzeViewList($view_dir = null)
210 if (is_null($view_dir)) {
211 $view_dir = $this->ctl->getViewdir();
213 $prefix_len = strlen($this->ctl->getViewdir());
215 $ext = '.' . $this->ctl->getExt('php');
216 $ext_len = strlen($ext);
218 $dh = opendir($view_dir);
220 while (($file = readdir($dh)) !== false) {
221 $path = "$view_dir/$file";
222 if ($file != '.' && $file != '..' && is_dir($path)) {
223 $tmp = $this->__analyzeViewList($path);
224 $r = array_merge($r, $tmp);
227 if (substr($file, -$ext_len, $ext_len) != $ext) {
232 $class_list = $this->__analyzeViewScript($path);
233 if (is_null($class_list) == false) {
234 $r = array_merge($r, $class_list);
247 * @return array ビュー一覧
249 function _getViewList()
251 $im =& new Ethna_InfoManager($this->backend);
252 //$view_class_list = array_keys($im->getForwardList());
256 // テンプレート/ビュースクリプトを解析する
257 $forward_list = $im->_analyzeForwardList();
258 $view_list = $this->__analyzeViewList();
261 $manifest_forward_list = $im->_getForwardList_Manifest($forward_list);
264 $implicit_forward_list = $im->_getForwardList_Implicit($forward_list, $manifest_forward_list);
266 $r = array_merge($view_list, $manifest_forward_list, $implicit_forward_list);
278 function _getTestAction()
280 $action_class_list = array_keys($this->_getActionList());
283 foreach ($action_class_list as $key => $action_name) {
284 $action_class = $this->ctl->getDefaultActionClass($action_name, false).'_TestCase';
285 if (!class_exists($action_class)) {
286 unset($action_class_list[$key]);
290 return $action_class_list;
299 function _getTestView()
301 $view_class_list = array_keys($this->_getViewList());
304 foreach ($view_class_list as $key => $view_name) {
305 $view_class = $this->ctl->getDefaultViewClass($view_name, false).'_TestCase';
306 if (!class_exists($view_class)) {
307 unset($view_class_list[$key]);
311 return $view_class_list;
318 * @return mixed 0:正常終了 Ethna_Error:エラー
322 $action_class_list = $this->_getTestAction();
323 $view_class_list = $this->_getTestView();
325 $test =& new GroupTest("Ethna UnitTest");
328 foreach ($action_class_list as $action_name) {
329 $action_class = $this->ctl->getDefaultActionClass($action_name, false).'_TestCase';
330 $action_form = $this->ctl->getDefaultFormClass($action_name, false).'_TestCase';
332 $test->addTestCase(new $action_class($this->ctl));
333 $test->addTestCase(new $action_form($this->ctl));
337 foreach ($view_class_list as $view_name) {
338 $view_class = $this->ctl->getDefaultViewClass($view_name, false).'_TestCase';
340 $test->addTestCase(new $view_class($this->ctl));
344 foreach ($this->testcase as $class_name => $file_name) {
345 $dir = $this->ctl->getBasedir().'/';
346 include_once $dir . $file_name;
347 $testcase_name = $class_name.'_TestCase';
348 $test->addTestCase(new $testcase_name($this->ctl));
352 $af =& $this->ctl->getActionForm();
355 $reporter = new Ethna_UnitTestReporter();
356 $test->run($reporter);
359 $this->ctl->action_form =& $af;
360 $this->backend->action_form =& $af;
361 $this->backend->af =& $af;
363 return array($reporter->report, $reporter->result);