diff --git a/module/bug/model.php b/module/bug/model.php index 880cc4841d..ffd6b1270f 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -91,6 +91,7 @@ class bugModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->bug->menu as $key => $menu) { + $this->loadModel('qa')->setSubMenu('bug', $key, $productID); if($this->config->global->flow != 'onlyTest') { $replace = $productID; diff --git a/module/caselib/model.php b/module/caselib/model.php index 1625001bec..93e433181e 100644 --- a/module/caselib/model.php +++ b/module/caselib/model.php @@ -118,6 +118,7 @@ class caselibModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->caselib->menu as $key => $value) { + $this->loadModel('qa')->setSubMenu('caselib', $key, $libID); $replace = $libID; common::setMenuVars($this->lang->caselib->menu, $key, $replace); } diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 26e34c9e84..d4a008d3d9 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -271,17 +271,23 @@ $lang->qa = new stdclass(); $lang->qa->menu = new stdclass(); $lang->qa->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->qa->menu->testcase = array('link' => '用例|testcase|browse|productID=%s'); +$lang->qa->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'class' => 'dropdown dropdown-hover'); $lang->qa->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s'); $lang->qa->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s'); $lang->qa->menu->report = array('link' => '报告|testreport|browse|productID=%s'); $lang->qa->menu->caselib = array('link' => '用例库|caselib|browse'); +$lang->qa->subMenu = new stdclass(); +$lang->qa->subMenu->testcase = new stdclass(); +$lang->qa->subMenu->testcase->feature = array('link' => '功能测试|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit,showimport,groupcase,importfromlib', 'subModule' => 'tree,story'); +$lang->qa->subMenu->testcase->unit = array('link' => '单元测试|testcase|unit|productID=%s'); + $lang->bug = new stdclass(); $lang->bug->menu = new stdclass(); +$lang->bug->subMenu = $lang->qa->subMenu; $lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,resolve,close,activate,report,batchedit,batchactivate,confirmbug,assignto', 'subModule' => 'tree'); -$lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=%s'); +$lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'class' => 'dropdown dropdown-hover'); $lang->bug->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s'); $lang->bug->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s'); $lang->bug->menu->report = array('link' => '报告|testreport|browse|productID=%s'); @@ -289,8 +295,9 @@ $lang->bug->menu->caselib = array('link' => '用例库|caselib|browse'); $lang->testcase = new stdclass(); $lang->testcase->menu = new stdclass(); +$lang->testcase->subMenu = $lang->qa->subMenu; $lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit,showimport,groupcase,importfromlib', 'subModule' => 'tree'); +$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit,showimport,groupcase,importfromlib', 'subModule' => 'tree,story', 'class' => 'dropdown dropdown-hover'); $lang->testcase->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s'); $lang->testcase->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s'); $lang->testcase->menu->report = array('link' => '报告|testreport|browse|productID=%s'); @@ -298,8 +305,9 @@ $lang->testcase->menu->caselib = array('link' => '用例库|caselib|browse'); $lang->testtask = new stdclass(); $lang->testtask->menu = new stdclass(); +$lang->testtask->subMenu = $lang->qa->subMenu; $lang->testtask->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testtask->menu->testcase = array('link' => '用例|testcase|browse|productID=%s'); +$lang->testtask->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'class' => 'dropdown dropdown-hover'); $lang->testtask->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s', 'subModule' => 'testtask', 'alias' => 'view,create,edit,linkcase,cases,start,close,batchrun,groupcase,report'); $lang->testtask->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s'); $lang->testtask->menu->report = array('link' => '报告|testreport|browse|productID=%s'); @@ -307,8 +315,9 @@ $lang->testtask->menu->caselib = array('link' => '用例库|caselib|browse'); $lang->testsuite = new stdclass(); $lang->testsuite->menu = new stdclass(); +$lang->testsuite->subMenu = $lang->qa->subMenu; $lang->testsuite->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testsuite->menu->testcase = array('link' => '用例|testcase|browse|productID=%s'); +$lang->testsuite->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'class' => 'dropdown dropdown-hover'); $lang->testsuite->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s'); $lang->testsuite->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s', 'alias' => 'view,create,edit,linkcase'); $lang->testsuite->menu->report = array('link' => '报告|testreport|browse|productID=%s'); @@ -316,8 +325,9 @@ $lang->testsuite->menu->caselib = array('link' => '用例库|caselib|browse'); $lang->testreport = new stdclass(); $lang->testreport->menu = new stdclass(); +$lang->testreport->subMenu = $lang->qa->subMenu; $lang->testreport->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testreport->menu->testcase = array('link' => '用例|testcase|browse|productID=%s'); +$lang->testreport->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'class' => 'dropdown dropdown-hover'); $lang->testreport->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s'); $lang->testreport->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s'); $lang->testreport->menu->report = array('link' => '报告|testreport|browse|productID=%s', 'alias' => 'view,create,edit'); @@ -325,8 +335,9 @@ $lang->testreport->menu->caselib = array('link' => '用例库|caselib|browse') $lang->caselib = new stdclass(); $lang->caselib->menu = new stdclass(); +$lang->caselib->subMenu = $lang->qa->subMenu; $lang->caselib->menu->bug = array('link' => 'Bug|bug|browse|'); -$lang->caselib->menu->testcase = array('link' => '用例|testcase|browse|'); +$lang->caselib->menu->testcase = array('link' => '用例|testcase|browse|', 'class' => 'dropdown dropdown-hover'); $lang->caselib->menu->testtask = array('link' => '测试单|testtask|browse|'); $lang->caselib->menu->testsuite = array('link' => '套件|testsuite|browse|'); $lang->caselib->menu->report = array('link' => '报告|testreport|browse|'); diff --git a/module/qa/model.php b/module/qa/model.php index ea850948f1..1e3a92a28c 100644 --- a/module/qa/model.php +++ b/module/qa/model.php @@ -42,8 +42,45 @@ class qaModel extends model $this->lang->modulePageNav = $productIndex; foreach($this->lang->qa->menu as $key => $menu) { + $this->setSubMenu('qa', $key, $productID); $replace = $productID; common::setMenuVars($this->lang->qa->menu, $key, $replace); } } + + /** + * Set qa subMenu. + * + * @param string $module + * @param string $key + * @param int $id + * @access public + * @return void + */ + public function setSubMenu($module, $key, $id) + { + if(!isset($this->lang->$module->subMenu->$key)) return true; + + $moduleSubMenu = $this->lang->$module->subMenu->$key; + $subMenu = common::createSubMenu($this->lang->$module->subMenu->$key, $id); + $moduleName = $this->app->getModuleName(); + $methodName = $this->app->getMethodName(); + + if(!empty($subMenu)) + { + foreach($subMenu as $menuKey => $menu) + { + $itemMenu = zget($moduleSubMenu, $menuKey, ''); + $isActive['method'] = ($moduleName == strtolower($menu->link['module']) and $methodName == strtolower($menu->link['method'])); + $isActive['alias'] = ($moduleName == strtolower($menu->link['module']) and (is_array($itemMenu) and isset($itemMenu['alias']) and strpos($itemMenu['alias'], $methodName) !== false)); + $isActive['subModule'] = (is_array($itemMenu) and isset($itemMenu['subModule']) and strpos($itemMenu['subModule'], $moduleName) !== false); + if($isActive['method'] or $isActive['alias'] or $isActive['subModule']) + { + $this->lang->$module->menu->{$key}['link'] = $menu->text . "|" . join('|', $menu->link); + break; + } + } + $this->lang->$module->menu->{$key}['subMenu'] = $subMenu; + } + } } diff --git a/module/testcase/control.php b/module/testcase/control.php index 4ff0d1634d..803b926d37 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -141,6 +141,65 @@ class testcase extends control $this->display(); } + /** + * Browse unit cases. + * + * @param int $productID + * @param string $branch + * @access public + * @return void + */ + public function unit($productID = 0, $branch = '') + { + /* Set browseType, productID, moduleID and queryID. */ + $productID = $this->product->saveState($productID, $this->products); + $branch = ($branch === '') ? (int)$this->cookie->preBranch : (int)$branch; + + /* Set menu, save session. */ + $this->testcase->setMenu($this->products, $productID, $branch); + $this->session->set('caseList', $this->app->getURI(true)); + + /* Load lang. */ + $this->app->loadLang('testtask'); + $this->app->loadLang('project'); + + /* Get test cases. */ + $cases = $this->loadModel('testsuite')->getProductSuiteCases($productID, $branch, 'suite,id_desc', 'unit'); + + /* save session .*/ + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', false); + + $groupCases = array(); + foreach($cases as $case) $groupCases[(int)$case->suite][$case->id] = $case; + + $suites = $this->loadModel('testsuite')->getUnit($productID); + + /* Process case for check story changed. */ + $cases = $this->loadModel('story')->checkNeedConfirm($cases); + $cases = $this->testcase->appendData($cases); + + $showModule = !empty($this->config->datatable->testcaseBrowse->showModule) ? $this->config->datatable->testcaseBrowse->showModule : ''; + $this->view->modulePairs = $showModule ? $this->tree->getModulePairs($productID, 'case', $showModule) : array(); + + /* Assign. */ + $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common; + $this->view->position[] = html::a($this->createLink('testcase', 'unit', "productID=$productID&branch=$branch"), $this->products[$productID]); + $this->view->position[] = $this->lang->testcase->common; + + $this->view->productID = $productID; + $this->view->product = $this->product->getById($productID); + $this->view->productName = $this->products[$productID]; + $this->view->summary = $this->testcase->summary($cases); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->groupCases = $groupCases; + $this->view->branch = $branch; + $this->view->branches = $this->loadModel('branch')->getPairs($productID); + $this->view->suites = $suites; + $this->view->setModule = true; + + $this->display(); + } + /** * Group case. * diff --git a/module/testcase/js/unit.js b/module/testcase/js/unit.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/module/testcase/lang/zh-cn.php b/module/testcase/lang/zh-cn.php index 15eda8dd9b..b9ad9d192e 100644 --- a/module/testcase/lang/zh-cn.php +++ b/module/testcase/lang/zh-cn.php @@ -167,6 +167,7 @@ $lang->testcase->priList[4] = 4; /* Define the types. */ $lang->testcase->typeList[''] = ''; $lang->testcase->typeList['feature'] = '功能测试'; +$lang->testcase->typeList['unit'] = '单元测试'; $lang->testcase->typeList['performance'] = '性能测试'; $lang->testcase->typeList['config'] = '配置相关'; $lang->testcase->typeList['install'] = '安装部署'; @@ -221,3 +222,6 @@ $lang->testcase->featureBar['browse']['group'] = '分组查看'; $lang->testcase->featureBar['browse']['suite'] = '套件'; $lang->testcase->featureBar['browse']['zerocase'] = "零用例{$lang->storyCommon}"; $lang->testcase->featureBar['groupcase'] = $lang->testcase->featureBar['browse']; + +$lang->testcase->featureBar['unit']['all'] = $lang->testcase->allCases; +$lang->testcase->featureBar['unit']['wait'] = '待评审'; diff --git a/module/testcase/model.php b/module/testcase/model.php index bc2c8308db..774bd11323 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -112,6 +112,7 @@ class testcaseModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->testcase->menu as $key => $menu) { + $this->loadModel('qa')->setSubMenu('testcase', $key, $productID); if($this->config->global->flow != 'onlyTest') { $replace = $productID; @@ -337,10 +338,11 @@ class testcaseModel extends model * @param int $moduleIdList * @param string $orderBy * @param object $pager + * @param string $type nounit|unit * @access public * @return array */ - public function getModuleCases($productID, $branch = 0, $moduleIdList = 0, $orderBy = 'id_desc', $pager = null, $browseType = '') + public function getModuleCases($productID, $branch = 0, $moduleIdList = 0, $orderBy = 'id_desc', $pager = null, $browseType = '', $type = 'nounit') { return $this->dao->select('t1.*, t2.title as storyTitle')->from(TABLE_CASE)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id') @@ -348,6 +350,8 @@ class testcaseModel extends model ->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi() ->beginIF($moduleIdList)->andWhere('t1.module')->in($moduleIdList)->fi() ->beginIF($browseType == 'wait')->andWhere('t1.status')->eq($browseType)->fi() + ->beginIF($type == 'nounit')->andWhere('t1.type')->ne('unit')->fi() + ->beginIF($type == 'unit')->andWhere('t1.type')->eq('unit')->fi() ->andWhere('t1.deleted')->eq('0') ->orderBy($orderBy)->page($pager)->fetchAll('id'); } @@ -436,10 +440,11 @@ class testcaseModel extends model * @param int $moduleID * @param string $sort * @param object $pager + * @param string $type nounit|unit * @access public * @return array */ - public function getTestCases($productID, $branch, $browseType, $queryID, $moduleID, $sort, $pager) + public function getTestCases($productID, $branch, $browseType, $queryID, $moduleID, $sort, $pager, $type = 'nounit') { /* Set modules and browse type. */ $modules = $moduleID ? $this->loadModel('tree')->getAllChildId($moduleID) : '0'; @@ -449,7 +454,7 @@ class testcaseModel extends model $cases = array(); if($browseType == 'bymodule' or $browseType == 'all' or $browseType == 'wait') { - $cases = $this->getModuleCases($productID, $branch, $modules, $sort, $pager, $browseType); + $cases = $this->getModuleCases($productID, $branch, $modules, $sort, $pager, $browseType, $type); } /* Cases need confirmed. */ elseif($browseType == 'needconfirm') @@ -461,6 +466,8 @@ class testcaseModel extends model ->andWhere('t1.product')->eq($productID) ->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi() ->beginIF($modules)->andWhere('t1.module')->in($modules)->fi() + ->beginIF($type == 'nounit')->andWhere('t1.type')->ne('unit')->fi() + ->beginIF($type == 'unit')->andWhere('t1.type')->eq('unit')->fi() ->orderBy($sort) ->page($pager) ->fetchAll(); @@ -472,7 +479,7 @@ class testcaseModel extends model /* By search. */ elseif($browseType == 'bysearch') { - $cases = $this->getBySearch($productID, $queryID, $sort, $pager, $branch); + $cases = $this->getBySearch($productID, $queryID, $sort, $pager, $branch, $type); } return $cases; @@ -485,10 +492,11 @@ class testcaseModel extends model * @param int $queryID * @param string $orderBy * @param object $pager + * @param string $type nounit|unit * @access public * @return array */ - public function getBySearch($productID, $queryID, $orderBy, $pager = null, $branch = 0) + public function getBySearch($productID, $queryID, $orderBy, $pager = null, $branch = 0, $type = 'nounit') { if($queryID) { @@ -526,6 +534,8 @@ class testcaseModel extends model $cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery) ->beginIF($queryProductID != 'all')->andWhere('product')->eq($productID)->fi() + ->beginIF($type == 'nounit')->andWhere('t1.type')->ne('unit')->fi() + ->beginIF($type == 'unit')->andWhere('t1.type')->eq('unit')->fi() ->andWhere('deleted')->eq(0) ->orderBy($orderBy)->page($pager)->fetchAll('id'); diff --git a/module/testcase/view/unit.html.php b/module/testcase/view/unit.html.php new file mode 100644 index 0000000000..28cc3d4858 --- /dev/null +++ b/module/testcase/view/unit.html.php @@ -0,0 +1,178 @@ + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +?> +global->flow); +if(!isset($branch)) $branch = 0; +?> +global->flow == 'full'):?> + + +
+ +
+

+ testcase->noCase;?> + + createLink('testcase', 'create', "productID=$productID&branch=$branch&moduleID=$initModule"), " " . $lang->testcase->create, '', "class='btn btn-info'");?> + +

+
+ + + + + + + + + + + + + + + + + + + + + $cases):?> + name : ''; + ?> + + > + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
idAB;?> priAB;?>testcase->title;?> typeAB;?> testtask->lastRunAccount;?>testtask->lastRunTime;?> testtask->lastRunResult;?> testcase->status;?>testcase->bugsAB;?>testcase->resultsAB;?>testcase->stepNumberAB;?> actions;?>
+
$groupName", '', "class='text-primary'");?>
+
id);?>pri;?>' title='testcase->priList, $case->pri, $case->pri);?>'>testcase->priList, $case->pri, $case->pri);?>id", $case->title)) echo $case->title;?>case->typeList, $case->type, '');?>lastRunner);?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?> + needconfirm) + { + echo "({$lang->story->changed} "; + echo html::a(helper::createLink('testcase', 'confirmStoryChange', "caseID=$case->id"), $lang->confirm, 'hiddenwin'); + echo ")"; + } + else + { + echo ""; + echo $this->processStatus('testcase', $case); + echo ''; + } + ?> + bugs) ? html::a(inlink('bugs', "runID=0&caseID={$case->id}"), $case->bugs, '', "class='iframe'") : $case->bugs;?>results) ? html::a($this->createLink('testtask', 'results', "runID=0&caseID={$case->id}"), $case->results, '', "class='iframe'") : $case->results;?>stepNumber;?> + id", $case, 'list', '', '', 'iframe', true, "data-width='95%'");?> + id", '', 'list');?> + id", '', 'list', '', 'hiddenwin');?> +
+ +
+ diff --git a/module/testreport/model.php b/module/testreport/model.php index 224d4c3867..5687da5375 100644 --- a/module/testreport/model.php +++ b/module/testreport/model.php @@ -49,6 +49,7 @@ class testreportModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->testtask->menu as $key => $value) { + $this->loadModel('qa')->setSubMenu('testreport', $key, $productID); if($this->config->global->flow != 'onlyTest') { $replace = $productID; diff --git a/module/testsuite/model.php b/module/testsuite/model.php index 87a5515a2d..80c3f464b5 100644 --- a/module/testsuite/model.php +++ b/module/testsuite/model.php @@ -57,6 +57,7 @@ class testsuiteModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->testsuite->menu as $key => $value) { + $this->loadModel('qa')->setSubMenu('testsuite', $key, $productID); $replace = $productID; common::setMenuVars($this->lang->testsuite->menu, $key, $replace); } @@ -148,6 +149,24 @@ class testsuiteModel extends model ->fetchAll('id'); } + /** + * Get unit suite. + * + * @param int $productID + * @param string $orderBy + * @access public + * @return array + */ + public function getUnit($productID, $orderBy = 'id_desc') + { + return $this->dao->select("*")->from(TABLE_TESTSUITE) + ->where('product')->eq((int)$productID) + ->andWhere('deleted')->eq(0) + ->andWhere('type')->eq('unit') + ->orderBy($orderBy) + ->fetchAll('id'); + } + /** * Get test suite info by id. * @@ -164,6 +183,29 @@ class testsuiteModel extends model return $suite; } + /** + * Get product suite cases. + * + * @param int $productID + * @param int $branch + * @param string $orderBy + * @param string $type nounit|unit + * @access public + * @return array + */ + public function getProductSuiteCases($productID, $branch = 0, $orderBy = 'id_desc', $type = 'nounit') + { + return $this->dao->select('t1.*,t2.suite')->from(TABLE_CASE)->alias('t1') + ->leftJoin(TABLE_SUITECASE)->alias('t2')->on('t1.id=t2.case') + ->where('t1.product')->eq((int)$productID) + ->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi() + ->beginIF($type == 'nounit')->andWhere('t1.type')->ne('unit')->fi() + ->beginIF($type == 'unit')->andWhere('t1.type')->eq('unit')->fi() + ->andWhere('t1.deleted')->eq('0') + ->orderBy($orderBy) + ->fetchAll('id'); + } + /** * Update a test suite. * diff --git a/module/testtask/lang/zh-cn.php b/module/testtask/lang/zh-cn.php index 5f21b0ab24..489811a16b 100644 --- a/module/testtask/lang/zh-cn.php +++ b/module/testtask/lang/zh-cn.php @@ -116,6 +116,8 @@ $lang->testtask->confirmUnlinkCase = '您确认要移除该用例吗?'; $lang->testtask->noticeNoOther = '该产品还没有其他测试单'; $lang->testtask->noTesttask = '暂时没有测试单'; $lang->testtask->checkLinked = '请检查测试单的产品是否与项目相关联'; +$lang->testtask->noImportData = '导入的XML没有解析出数据。'; +$lang->testtask->unitXMLFormat = '请选择Junit XML 格式的文件。'; $lang->testtask->assignedToMe = '指派给我'; $lang->testtask->allCases = '所有用例'; diff --git a/module/testtask/model.php b/module/testtask/model.php index 2b3fc4c4ee..0164a7bcc8 100644 --- a/module/testtask/model.php +++ b/module/testtask/model.php @@ -79,6 +79,7 @@ class testtaskModel extends model $this->lang->modulePageActions = $pageActions; foreach($this->lang->testtask->menu as $key => $value) { + $this->loadModel('qa')->setSubMenu('testtask', $key, $productID); if($this->config->global->flow != 'onlyTest') { $replace = ($key == 'product') ? $selectHtml : $productID; @@ -1515,64 +1516,100 @@ class testtaskModel extends model $matchPaths = $unitFormat['path']; $nameFields = $unitFormat['name']; $failure = $unitFormat['failure']; + $matchNodes = array(); foreach($matchPaths as $matchPath) { $matchNodes = $parsedXML->xpath($matchPath); if(count($matchNodes) != 0) break; } + if(count($matchNodes) == 0) die(js::alert($this->lang->testtask->noImportData)); + + $parentPath = ''; + $caseNode = $matchPath; + $parentNodes = array($parsedXML); + if(strpos($matchPath, '/') !== false) + { + $explodedPath = explode('/', $matchPath); + $caseNode = array_pop($explodedPath); + $parentPath = implode('/', $explodedPath); + $parentNodes = $parsedXML->xpath($parentPath); + } /* Get cases and results by parsed node. */ - $now = helper::now(); - $cases = array(); - $titles = array(); - $results = array(); - foreach($matchNodes as $i => $matchNode) + $now = helper::now(); + $cases = array(); + $results = array(); + $suites = array(); + $caseTitles = array(); + $suiteNames = array(); + foreach($parentNodes as $suiteIndex => $parentNode) { - $case = new stdclass(); - $case->product = $productID; - $case->title = ''; - $case->pri = 3; - $case->type = 'feature'; - $case->stage = 'unittest'; - $case->status = 'normal'; - $case->openedBy = $this->app->user->account; - $case->openedDate = $now; - $case->version = 1; - - $attributes = $matchNode->attributes(); - foreach($nameFields as $field) $case->title .= (string)$attributes[$field] . ' '; - $case->title = trim($case->title); - - $result = new stdclass(); - $result->case = 0; - $result->version = 1; - $result->caseResult = 'pass'; - $result->lastRunner = $this->app->user->account; - $result->date = $now; - $result->stepResults[0]['result'] = 'pass'; - $result->stepResults[0]['real'] = ''; - if(isset($matchNode->$failure)) + $attributes = $parentNode->attributes(); + $suite = ''; + if(isset($attributes['name'])) { - $result->caseResult = 'fail'; - $result->stepResults[0]['result'] = 'fail'; - if(is_string($matchNode->$failure)) - { - $result->stepResults[0]['real'] = (string)$matchNode->$failure; - } - else - { - $failureAttrs = $matchNode->$failure->attributes(); - $result->stepResults[0]['real'] = (string)$failureAttrs['message']; - } + $suite = new stdclass(); + $suite->product = $productID; + $suite->name = (string)$attributes['name']; + $suite->type = 'unit'; + $suite->addedBy = $this->app->user->account; + $suite->addedDate = $now; + $suiteNames[] = $suite->name; } - $result->stepResults = serialize($result->stepResults); - $case->lastRunner = $this->app->user->account; - $case->lastRunDate = $now; - $case->lastRunResult = $result->caseResult; + $suites[$suiteIndex] = $suite; - $titles[] = $case->title; - $cases[$i] = $case; - $results[$i] = $result; + foreach($parentNode->xpath($caseNode) as $caseIndex => $matchNode) + { + $case = new stdclass(); + $case->product = $productID; + $case->title = ''; + $case->pri = 3; + $case->type = 'unit'; + $case->stage = 'unittest'; + $case->status = 'normal'; + $case->openedBy = $this->app->user->account; + $case->openedDate = $now; + $case->version = 1; + + $attributes = $matchNode->attributes(); + foreach($nameFields as $field) + { + if(!isset($attributes[$field])) continue; + $case->title .= (string)$attributes[$field] . ' '; + } + $case->title = trim($case->title); + + $result = new stdclass(); + $result->case = 0; + $result->version = 1; + $result->caseResult = 'pass'; + $result->lastRunner = $this->app->user->account; + $result->date = $now; + $result->stepResults[0]['result'] = 'pass'; + $result->stepResults[0]['real'] = ''; + if(isset($matchNode->$failure)) + { + $result->caseResult = 'fail'; + $result->stepResults[0]['result'] = 'fail'; + if(is_string($matchNode->$failure)) + { + $result->stepResults[0]['real'] = (string)$matchNode->$failure; + } + else + { + $failureAttrs = $matchNode->$failure->attributes(); + $result->stepResults[0]['real'] = (string)$failureAttrs['message']; + } + } + $result->stepResults = serialize($result->stepResults); + $case->lastRunner = $this->app->user->account; + $case->lastRunDate = $now; + $case->lastRunResult = $result->caseResult; + + $titles[$suiteIndex][] = $case->title; + $cases[$suiteIndex][$caseIndex] = $case; + $results[$suiteIndex][$caseIndex] = $result; + } } /* Create task. */ @@ -1581,37 +1618,80 @@ class testtaskModel extends model if(dao::isError()) return false; /* Import cases and link task and insert result. */ - $existCases = $this->dao->select('*')->from(TABLE_CASE)->where('title')->in($titles)->andWhere('stage')->eq('unittest')->andWhere('deleted')->eq(0)->fetchPairs('title', 'id'); $this->loadModel('action'); - foreach($cases as $i => $case) + $existSuites = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('name')->in($suiteNames)->andWhere('product')->eq($productID)->andWhere('type')->eq('unit')->andWhere('deleted')->eq(0)->fetchPairs('name', 'id'); + foreach($suites as $suiteIndex => $suite) { - if(!isset($existCases[$case->title])) + $suiteID = 0; + if($suite) { - $this->dao->insert(TABLE_CASE)->data($case)->exec(); - $caseID = $this->dao->lastInsertID(); - $this->action->create('case', $caseID, 'Opened'); + if(!isset($existSuites[$suite->name])) + { + $this->dao->insert(TABLE_TESTSUITE)->data($suite)->exec(); + $suiteID = $this->dao->lastInsertID(); + $this->action->create('testsuite', $suiteID, 'opened'); + } + else + { + $suiteID = $existSuites[$suite->name]; + } + } + + if($suiteID) + { + $existCases = $this->dao->select('t1.*')->from(TABLE_CASE)->alias('t1') + ->leftJoin(TABLE_SUITECASE)->alias('t2')->on('t1.id=t2.case') + ->where('t1.title')->in($caseTitles[$suiteIndex]) + ->andWhere('t1.product')->eq($productID) + ->andWhere('t1.stage')->eq('unittest') + ->andWhere('t1.deleted')->eq(0) + ->fetchPairs('title', 'id'); } else { - $caseID = $existCases[$case->title]; + $existCases = $this->dao->select('*')->from(TABLE_CASE)->where('title')->in($caseTitles[$suiteIndex])->andWhere('product')->eq($productID)->andWhere('stage')->eq('unittest')->andWhere('deleted')->eq(0)->fetchPairs('title', 'id'); } - $testrun = new stdclass(); - $testrun->task = $testtaskID; - $testrun->case = $caseID; - $testrun->version = $case->version; - $testrun->lastRunner = $case->lastRunner; - $testrun->lastRunDate = $case->lastRunDate; - $testrun->lastRunResult = $case->lastRunResult; - $testrun->status = 'done'; + foreach($cases[$suiteIndex] as $i => $case) + { + if(!isset($existCases[$case->title])) + { + $this->dao->insert(TABLE_CASE)->data($case)->exec(); + $caseID = $this->dao->lastInsertID(); + $this->action->create('case', $caseID, 'Opened'); + } + else + { + $caseID = $existCases[$case->title]; + } - $this->dao->replace(TABLE_TESTRUN)->data($testrun)->exec(); - $runID = $this->dao->lastInsertID(); + if($suiteID) + { + $suitecase = new stdclass(); + $suitecase->suite = $suiteID; + $suitecase->case = $caseID; + $suitecase->version = $case->version; + $suitecase->product = $case->product; + $this->dao->replace(TABLE_SUITECASE)->data($suitecase)->exec(); + } - $testresult = $results[$i]; - $testresult->run = $runID; - $testresult->case = $caseID; - $this->dao->insert(TABLE_TESTRESULT)->data($testresult)->exec(); + $testrun = new stdclass(); + $testrun->task = $testtaskID; + $testrun->case = $caseID; + $testrun->version = $case->version; + $testrun->lastRunner = $case->lastRunner; + $testrun->lastRunDate = $case->lastRunDate; + $testrun->lastRunResult = $case->lastRunResult; + $testrun->status = 'done'; + + $this->dao->replace(TABLE_TESTRUN)->data($testrun)->exec(); + $runID = $this->dao->lastInsertID(); + + $testresult = $results[$suiteIndex][$i]; + $testresult->run = $runID; + $testresult->case = $caseID; + $this->dao->insert(TABLE_TESTRESULT)->data($testresult)->exec(); + } } return $testtaskID; diff --git a/module/testtask/view/importunit.html.php b/module/testtask/view/importunit.html.php index 2ab704e982..370b666e18 100644 --- a/module/testtask/view/importunit.html.php +++ b/module/testtask/view/importunit.html.php @@ -67,6 +67,7 @@ testtask->resultFile;?> + testtask->unitXMLFormat;?> testtask->name;?>