loadCommon() 方法创建名为 tester 的commonModel对象。 * This file build a app instance and provide a instance of commonModel named as tester by $app->loadCommon(). * * All request of entries should be routed by this router. * * @copyright Copyright 2009-2017 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com) * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html) * @author Guanxing * @package ZenTaoPMS * @version $Id: $ * @link http://www.zentao.net */ /* Set the error reporting. */ error_reporting(E_ALL); define('RUN_MODE', 'test'); if(!defined('LIB_ROOT')) define('LIB_ROOT', dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR); include_once LIB_ROOT . 'coverage.php'; $codeCoverageConfig = dirname(LIB_ROOT) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'my.php'; $codeCoverageConfig = exec("sed -n 's/^\\\$config->codeCoverage *= *\\(.*\\);/\\1/p' $codeCoverageConfig"); if($argc > 1 && $argv[1] == '-extract') { printSteps(); exit; } $zentaoRoot = dirname(__FILE__, 3) . DIRECTORY_SEPARATOR; $testPath = $zentaoRoot . 'test' . DIRECTORY_SEPARATOR; $frameworkRoot = $zentaoRoot . 'framework' . DIRECTORY_SEPARATOR; if(isset($codeCoverageConfig) and $codeCoverageConfig == 'true') { $coverage = new coverage(); $coverage->startCodeCoverage(); } /** * Assert status code and set body as $_result. * * @param int $code * @access public * @return bool */ function c($code) { global $_result; if(empty($_result) or empty($_result->status_code)) return false; $codeStr = (string)$code; $statusCodeStr = (string)($_result->status_code); if($_result->status_code == $code or ($statusCodeStr[0] === '2' and $codeStr[0] === '2')) { $_result = $_result->body; return true; } echo "\n\n"; return false; } /* Load the framework. */ include $frameworkRoot . 'router.class.php'; include $frameworkRoot . 'control.class.php'; include $frameworkRoot . 'model.class.php'; include $frameworkRoot . 'helper.class.php'; $app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); $poolID = getenv('ZTF_POOL_ID'); $dbPool = empty($config->dbPool) ? array() : $config->dbPool; /* 根据ztf设置的poolID环境变量设置连接的数据库 */ if(!empty($dbPool) && !empty($poolID)) { $selectDB = $dbPool[$poolID%count($dbPool)]; !empty($selectDB['host']) && $config->db->host = $selectDB['host']; !empty($selectDB['port']) && $config->db->port = $selectDB['port']; !empty($selectDB['name']) && $config->db->name = $selectDB['name']; !empty($selectDB['user']) && $config->db->user = $selectDB['user']; !empty($selectDB['password']) && $config->db->password = $selectDB['password']; $app->connectDB(); } $tester = $app->loadCommon(); /* Set configs. */ $config->zendataRoot = dirname(dirname(__FILE__)) . '/zendata'; $config->ztfPath = dirname(dirname(__FILE__)) . '/tools/ztf'; $config->zdPath = dirname(dirname(__FILE__)) . '/tools/zd'; /* init testDB. */ include $testPath . 'lib/yaml.class.php'; include $testPath . 'lib/rest.php'; if(!empty($config->test->account) and !empty($config->test->password) and !empty($config->test->base)) { $rest = new rest($config->test->base); $token = $rest->post('/tokens', array('account' => $config->test->account, 'password' => $config->test->password)); $token = $token->body; } /** * Save variable to $_result. * * @param mixed $result * @access public * @return bool true */ function r($result) { global $_result; $_result = $result; return true; } /** * Print value or properties. * * @param string $key * @param string $delimiter * @access public * @return void */ function p($keys = '', $delimiter = ',') { global $_result; if(empty($_result)) return print(implode("\n", array_fill(0, substr_count($keys, $delimiter) + 1, 0)) . "\n"); if(is_array($_result) && isset($_result['code']) && $_result['code'] == 'fail') return print((string) $_result['message'] . "\n"); /* Print $_result. */ if($keys === '' && is_array($_result)) return print_r($_result) . "\n"; if($keys === '' || !is_array($_result) && !is_object($_result)) return print((string) $_result . "\n"); $parts = explode(';', $keys); foreach($parts as $part) { $values = getValues($_result, $part, $delimiter); if(!is_array($values)) continue; foreach($values as $value) echo $value . "\n"; } return true; } /** * 生成用例步骤描述 * Generate step desc. * * @param string $userStep * @param string $moduleName * @param string $methodName * @param string $methodParam * @param string $isGroup * @access public * @return string */ function genStepDesc($userStep, $moduleName, $methodName, $methodParam, $isGroup) { if($userStep) return '- ' . $userStep . ($isGroup ? "\n" : ''); if ($methodName === 0 && $methodParam === 0) { $stepDesc = "- 执行{$moduleName}" . ($isGroup ? "\n" : ''); } elseif($methodParam) { $stepDesc = "- 执行{$moduleName}模块的{$methodName}方法,参数是{$methodParam}" . ($isGroup ? "\n" : ' '); } else { $stepDesc = "- 执行{$moduleName}模块的{$methodName}方法" . ($isGroup ? "\n" : ' '); } return $stepDesc; } /** * 用例步骤并输出(ztf使用) * Print steps by row. * * @param string $key * @access public * @return void */ function printSteps() { $debugInfo = debug_backtrace(); if(empty($debugInfo)) return; $file = $debugInfo[count($debugInfo)-1]['file']; $contents = file_get_contents($file); $rpeList = genParamsByRPE($contents); $desc = ''; foreach($rpeList as $rpe) { list($moduleName, $methodName, $methodParam) = $rpe[0]; $isGroup = false; $pParam = $rpe[2]; $keys = $pParam[0]; $delimiter = $pParam[1] ? $pParam[1] : ','; $parts = explode(';', $keys); $parts = array_filter($parts); $userStep = trim(str_replace('//', '', $rpe[3])); $expectStr = is_numeric($rpe[1]) ? $rpe[1] : trim($rpe[1], substr($rpe[1], 0, 1)); $stepDesc = genStepDesc($userStep, $moduleName, $methodName, $methodParam, $isGroup); if(empty($keys)) $stepDesc .= " @{$expectStr}\n"; if(str_contains($keys, ';') && str_contains($expectStr, ';')) { $expectList = explode(';', $expectStr); $expectList = array_map(function($item) use ($delimiter) { return explode($delimiter, $item); }, $expectList); } else { $expectList = explode($delimiter, $expectStr); $chunkCount = empty($parts) ? 1 : ceil(count($expectList)/count($parts)); $expectList = array_chunk($expectList, $chunkCount); } $isGroup = count($expectList) > 1 || (!empty($expectList) && count($expectList[0]) > 1); $desc .= $stepDesc; if($isGroup && substr($desc, -2) != "\n") $desc .= "\n"; foreach($parts as $index => $part) { $desc .= genRowStep($part, $delimiter, $expectList[$index], $isGroup); } // $desc .= "\n"; } echo trim($desc); } /** * 生成(;隔开的)每条数据的用例步骤. * Generate steps by row. * * @param string $key * @access public * @return string */ function genRowStep($keys, $delimiter, $expects, $isGroup) { $stepDesc = ''; $rowIndex = -1; $pos = strpos($keys, ':'); if($pos) { $rowIndex = substr($keys, 0, $pos); $keys = substr($keys, $pos + 1); } $keys = $keys === '' ? array() : explode($delimiter, $keys); foreach($keys as $index => $row) { $stepExpect = isset($expects[$index]) ? $expects[$index] : ''; if(count($expects) == 1) $stepExpect = current($expects); if($rowIndex == -1) { $stepDesc .= ($isGroup ? ' - ' : '') . ($row ? "属性{$row}" : '') . " @{$stepExpect}\n"; } else { $stepDesc .= ($isGroup ? ' - ' : '') . "第{$rowIndex}条的{$row}属性 @{$stepExpect}\n"; } } return $stepDesc; } /** * 从p()函数提取传入参数 * Split function params. * * @param array $params * @return array */ function splitParam($params) { $newParams = array(); foreach($params as $param) { $param = trim($param); $firstSymbol = substr($param, 0, 1); $paramList = str_split($param); $delimiterIndex = -1; foreach($paramList as $i => $p) { if($i == 0) continue; if($p === $firstSymbol && (!isset($paramList[$i-1]) || '\\' != $paramList[$i-1])) { $delimiterIndex = $i + 1; break; } } if($delimiterIndex === -1) { $newParams[] = array($param, ''); continue; } $firstParam = substr($param, 0, $delimiterIndex); $firstParam = trim(trim($firstParam), '\'"'); $lastParam = substr($param, $delimiterIndex + 1); $lastParam = trim(trim($lastParam), '\'"'); $newParams[] = array($firstParam, $lastParam); } return $newParams; } /** * 从r()函数提取调用的moduleName,methodName,methodParam * Generate module,method,param from r function. * * @param array $rParams * @return array */ function genModuleAndMethod($rParams) { $newParams = array(); foreach($rParams as $param) { $param = trim($param, "'"); if($param[0] != '$') $param = trim(strchr($param, '$'), ')'); $objArrowCount = substr_count($param, '->'); $rParamsStructureList = explode('->', $param); if($objArrowCount == 1 && str_contains($rParamsStructureList[1], '(')) { $moduleName = substr($rParamsStructureList[0], 1); $method = $rParamsStructureList[1]; $methodName = substr(explode('(', $method)[0], 0); $methodParam = substr(explode('(', $method)[1], 0); $methodParam = trim($methodParam, "()"); } elseif($objArrowCount == 2) { $moduleName = $rParamsStructureList[1]; $method = $rParamsStructureList[2]; $methodName = explode('(', $method)[0]; $methodParam = trim(substr(explode('(', $method)[1], 0), "()"); } else { $newParams[] = array($param, 0, 0); continue; } $methodParam = preg_replace("/,\s*/", ', ', $methodParam); $newParams[] = array($moduleName, $methodName, $methodParam); } return $newParams; } /** * 从RPE中获取模块,方法以及参数 * Generate method,module,params from rpe. * * @param string $rpe * @return array */ function genParamsByRPE($rpe) { preg_match_all("/\nr\((.*?)\)\s*&&\s*p\((.*?)\)\s*&&\s*e\((.*?)\);(.*)/", $rpe, $matches); $rParams = !empty($matches[1]) ? $matches[1] : array(); $pParams = !empty($matches[2]) ? $matches[2] : array(); $eParams = !empty($matches[3]) ? $matches[3] : array(); $stepList = !empty($matches[4]) ? $matches[4] : array(); $rParams = is_array($rParams) ? $rParams : array($rParams); $pParams = is_array($pParams) ? $pParams : array($pParams); $eParams = is_array($eParams) ? $eParams : array($eParams); $pParamsList = splitParam($pParams); $rpeList = array(); $rParamList = genModuleAndMethod($rParams); foreach($rParamList as $index => $param) $rpeList[] = array($param, $eParams[$index], $pParamsList[$index], $stepList[$index]); return $rpeList; } /** * Get values * * @param mixed $value * @param string $keys * @param string $delimiter * @access public * @return void */ function getValues($value, $keys, $delimiter) { $object = ''; $index = -1; $pos = strpos($keys, ':'); if($pos) { $arrKey = substr($keys, 0, $pos); $keys = substr($keys, $pos + 1); $pos = strpos($arrKey, '['); if($pos) { $object = substr($arrKey, 0, $pos); $index = trim(substr($arrKey, $pos + 1), ']'); } else { $index = $arrKey; } } $keys = explode($delimiter, $keys); if($object !== '') { if(is_array($value)) { $value = $value[$object]; } else if(is_object($value)) { $value = $value->$object; } else { return print("Error: No object name '$object'.\n"); } } if($index != -1) { if(is_array($value)) { if(!isset($value[$index])) return print("Error: Cannot get index $index.\n"); $value = $value[$index]; } else if(is_object($value)) { if(!isset($value->$index)) return print("Error: Cannot get index $index.\n"); $value = $value->$index; } else { return print("Error: Not array, cannot get index $index.\n"); } } $values = array(); foreach($keys as $key) $values[] = zget($value, $key, ''); return $values; } /** * Expect values, ztf will put params to step. * * @param string $exepect * @access public * @return void */ function e($expect) { global $codeCoverageConfig; global $coverage; if(isset($codeCoverageConfig) and $codeCoverageConfig == 'true') $coverage->saveAndRestartCodeCoverage(); } /** * Check order * * @param array $objs * @param string $orderBy * @access public * @return bool */ function checkOrder($objs, $orderBy) { if(empty($objs)) return true; list($field, $sort) = explode('_', $orderBy); $last = current($objs)->$field; foreach($objs as $obj) { if($sort == 'desc') { if($obj->$field > $last) return false; } else { if($obj->$field < $last) return false; } } return true; } /** * Import data create by zendata to one table. * * @param string $table * @param string $yaml * @param int $count * @access public * @return void */ function zdImport($table, $yaml, $count = 10) { chdir(dirname(__FILE__)); global $app, $config; $dns = "mysql://{$config->db->user}:{$config->db->password}@{$config->db->host}:{$config->db->port}/{$config->db->name}#utf8"; $table = trim($table, '`'); $command = "$config->zdPath -c $yaml -t $table -T -dns $dns --clear -n $count"; system($command); } /** * Switch user. * * @param string $account * @access public * @return bool */ function su($account) { $userModel = new userModel(); $user = $userModel->getByID($account); if($user) return $userModel->login($user); $user = $userModel->identify($account, $user->password); return false; }