diff --git a/config/config.php b/config/config.php index 55b41cd275..fe735270cc 100644 --- a/config/config.php +++ b/config/config.php @@ -76,7 +76,7 @@ define('TABLE_USER', $config->db->prefix . 'user'); define('TABLE_GROUP', $config->db->prefix . 'group'); define('TABLE_USERGROUP', $config->db->prefix . 'userGroup'); define('TABLE_GROUPPRIV', $config->db->prefix . 'groupPriv'); -define('TABLE_PLANCASE', $config->db->prefix . 'planCase'); +define('TABLE_TASKCASE', $config->db->prefix . 'taskCase'); define('TABLE_PRODUCT', $config->db->prefix . 'product'); define('TABLE_PRODUCTPLAN', $config->db->prefix . 'productPlan'); define('TABLE_RELEASE', $config->db->prefix . 'release'); @@ -88,7 +88,7 @@ define('TABLE_STORY', $config->db->prefix . 'story'); define('TABLE_PROJECTSTORY', $config->db->prefix . 'projectStory'); define('TABLE_TASK', $config->db->prefix . 'task'); define('TABLE_TASKESTIMATE', $config->db->prefix . 'taskEstimate'); -define('TABLE_TESTPLAN', $config->db->prefix . 'testPlan'); +define('TABLE_TESTTASK', $config->db->prefix . 'testTask'); define('TABLE_PROJECTPRODUCT', $config->db->prefix . 'projectProduct'); define('TABLE_TODO', $config->db->prefix . 'todo'); define('TABLE_BURN', $config->db->prefix . 'burn'); diff --git a/module/bug/model.php b/module/bug/model.php index 0c857f8385..9cfa18d22a 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -32,6 +32,7 @@ class bugModel extends model common::setMenuVars($this->lang->bug->menu, 'product', $selectHtml . $this->lang->arrow); common::setMenuVars($this->lang->bug->menu, 'bug', $productID); common::setMenuVars($this->lang->bug->menu, 'testcase', $productID); + common::setMenuVars($this->lang->bug->menu, 'testtask', $productID); } /* 创建一个Bug。*/ diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 0dec9ef110..821608d0eb 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -107,10 +107,17 @@ $lang->build->menu = $lang->project->menu; $lang->bug->menu->product = '%s'; $lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,active', 'subModule' => 'tree'); $lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); +$lang->bug->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); $lang->testcase->menu->product = '%s'; $lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,active'); $lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); + +$lang->testtask->menu->product = '%s'; +$lang->testtask->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,active'); +$lang->testtask->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit', 'subModule' => 'tree'); +$lang->testtask->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase'); /* 组织结构视图菜单设置。*/ $lang->company->menu->browseUser = array('link' => '用户列表|company|browse', 'subModule' => 'user'); @@ -151,6 +158,7 @@ $lang->menugroup->user = 'company'; $lang->menugroup->group = 'company'; $lang->menugroup->bug = 'qa'; $lang->menugroup->testcase = 'qa'; +$lang->menugroup->testtask = 'qa'; $lang->menugroup->people = 'company'; $lang->menugroup->dept = 'company'; $lang->menugroup->todo = 'my'; diff --git a/module/testcase/model.php b/module/testcase/model.php index 51e823c786..bb52402395 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -32,6 +32,7 @@ class testcaseModel extends model common::setMenuVars($this->lang->testcase->menu, 'product', $selectHtml . $this->lang->arrow); common::setMenuVars($this->lang->testcase->menu, 'bug', $productID); common::setMenuVars($this->lang->testcase->menu, 'testcase', $productID); + common::setMenuVars($this->lang->testcase->menu, 'testtask', $productID); } /* 创建一个Case。*/ diff --git a/module/testtask/config.php b/module/testtask/config.php new file mode 100644 index 0000000000..50e94fa7bd --- /dev/null +++ b/module/testtask/config.php @@ -0,0 +1,22 @@ +loadLang('testcase'); +$config->testcase->search['module'] = 'testcase'; +$config->testcase->search['fields']['id'] = $lang->testcase->id; +$config->testcase->search['fields']['title'] = $lang->testcase->title; +$config->testcase->search['fields']['steps'] = $lang->testcase->steps; +$config->testcase->search['fields']['openedBy'] = $lang->testcase->openedBy; +$config->testcase->search['fields']['lastEditedBy'] = $lang->testcase->lastEditedBy; +$config->testcase->search['fields']['status'] = $lang->testcase->status; +$config->testcase->search['fields']['pri'] = $lang->testcase->pri; +$config->testcase->search['fields']['type'] = $lang->testcase->type; +$config->testcase->search['fields']['openedDate'] = $lang->testcase->openedDate; +$config->testcase->search['fields']['lastEditedDate'] = $lang->testcase->lastEditedDate; + +$config->testcase->search['params']['title'] = array('operator' => 'include', 'control' => 'input', 'values' => ''); +$config->testcase->search['params']['steps'] = array('operator' => 'include', 'control' => 'input', 'values' => ''); +$config->testcase->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users'); +$config->testcase->search['params']['lastEditedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users'); +$config->testcase->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->testcase->statusList); +$config->testcase->search['params']['pri'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->testcase->priList); +$config->testcase->search['params']['type'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->testcase->typeList); diff --git a/module/testtask/control.php b/module/testtask/control.php new file mode 100644 index 0000000000..682508491c --- /dev/null +++ b/module/testtask/control.php @@ -0,0 +1,190 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +class testtask extends control +{ + private $products = array(); + + /* 构造函数,加载story, release, tree等模块。*/ + public function __construct() + { + parent::__construct(); + $this->loadModel('product'); + $this->view->products = $this->products = $this->product->getPairs(); + } + + /* task首页。*/ + public function index() + { + $this->locate($this->createLink('testtask', 'browse')); + } + + /* 浏览一个产品下面的task。*/ + public function browse($productID = 0, $orderBy = 'id|desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* 设置产品和菜单。*/ + $productID = common::saveProductState($productID, key($this->products)); + $this->testtask->setMenu($this->products, $productID); + + /* 加载分页类。*/ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* 赋值。*/ + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->common; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->common; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->pager = $pager; + $this->view->orderBy = $orderBy; + $this->view->tasks = $this->testtask->getProductTasks($productID); + + $this->display(); + } + + /* 创建task。*/ + public function create($productID) + { + if(!empty($_POST)) + { + $taskID = $this->testtask->create($productID); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('testtask', 'browse', "productID=$productID"), 'parent')); + } + + /* 设置菜单。*/ + $productID = common::saveProductState($productID, key($this->products)); + $this->testtask->setMenu($this->products, $productID); + + /* 导航信息。*/ + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->create; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->create; + + $this->view->projects = $this->product->getProjectPairs($productID); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); + + $this->display(); + } + + /* 查看一个task。*/ + public function view($taskID) + { + /* 获取task和产品信息,并设置菜单。*/ + $task = $this->testtask->getById($taskID); + $productID = $task->product; + $this->testtask->setMenu($this->products, $productID); + + /* 导航信息。*/ + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->view; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->view; + + /* 赋值。*/ + $this->view->task = $task; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->cases = $this->testtask->getCases($taskID); + + $this->display(); + } + + /* 编辑一个Bug。*/ + public function edit($taskID) + { + /* 获得task信息。*/ + $task = $this->testtask->getById($taskID); + $productID = common::saveProductState($task->product, key($this->products)); + + /* 更新task信息。*/ + if(!empty($_POST)) + { + $this->testtask->update($taskID); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate(inlink('browse', "productID=$productID"), 'parent')); + } + + /* 设置菜单。*/ + $this->testtask->setMenu($this->products, $productID); + + /* 导航信息。*/ + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->edit; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->edit; + + $this->view->task = $task; + $this->view->projects = $this->product->getProjectPairs($productID); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); + + $this->display(); + } + + /* 删除一个任务。*/ + public function delete($taskID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->testtask->confirmDelete, inlink('delete', "taskID=$taskID&confirm=yes"))); + } + else + { + $task = $this->testtask->getByID($taskID); + $this->testtask->delete($taskID); + die(js::locate(inlink('browse', "product=$task->product"), 'parent')); + } + } + + /* 关联用例。*/ + public function linkCase($taskID) + { + if(!empty($_POST)) + { + $this->testtask->linkCase($taskID); + $this->locate(inlink('view', "taskID=$taskID")); + } + + /* 构造搜索表单。*/ + $this->config->testcase->search['actionURL'] = inlink('linkcase', "taskID=$taskID"); + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->testcase->search); + + /* 获得task信息。*/ + $task = $this->testtask->getById($taskID); + $productID = common::saveProductState($task->product, key($this->products)); + + /* 设置菜单。*/ + $this->testtask->setMenu($this->products, $productID); + + /* 导航信息。*/ + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->linkCase; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->linkCase; + + /* 获得用例列表。*/ + if($this->session->testcaseQuery == false) $this->session->set('testcaseQuery', ' 1 = 1'); + $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQuery)->andWhere('product')->eq($productID)->orderBy('id desc')->fetchAll(); + + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + + $this->display(); + } +} diff --git a/module/testtask/lang/zh-cn.php b/module/testtask/lang/zh-cn.php new file mode 100644 index 0000000000..4abaf1773d --- /dev/null +++ b/module/testtask/lang/zh-cn.php @@ -0,0 +1,51 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +$lang->testtask->id = '任务编号'; +$lang->testtask->product = '所属产品'; +$lang->testtask->project = '所属项目'; +$lang->testtask->build = '相关Build'; +$lang->testtask->name = '测试任务名称'; +$lang->testtask->begin = '开始日期'; +$lang->testtask->end = '结束日期'; +$lang->testtask->desc = '任务描述'; +$lang->testtask->status = '测试任务状态'; + +$lang->testtask->common = '测试任务'; +$lang->testtask->index = "测试任务首页"; +$lang->testtask->create = "创建测试任务"; +$lang->testtask->delete = "删除测试任务"; +$lang->testtask->view = "测试任务详情"; +$lang->testtask->edit = "编辑测试任务"; +$lang->testtask->browse = "测试任务列表"; +$lang->testtask->linkCase = "关联用例"; +$lang->testtask->unlinkCase = "移除用例"; +$lang->testtask->executeCase = "执行用例"; + +$lang->testtask->statusList['wait'] = '未开始'; +$lang->testtask->statusList['doing'] = '进行中'; +$lang->testtask->statusList['done'] = '已完成'; + +$lang->testtask->unlinkedCases = '未关联用例列表'; +$lang->testtask->linkedCases = '已关联用例列表'; +$lang->testtask->confirmDelete = '您确认要删除改测试任务吗?'; diff --git a/module/testtask/model.php b/module/testtask/model.php new file mode 100644 index 0000000000..57ea4b8c70 --- /dev/null +++ b/module/testtask/model.php @@ -0,0 +1,107 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +?> +lang->testtask->menu, 'product', $selectHtml . $this->lang->arrow); + common::setMenuVars($this->lang->testtask->menu, 'bug', $productID); + common::setMenuVars($this->lang->testtask->menu, 'testcase', $productID); + common::setMenuVars($this->lang->testtask->menu, 'testtask', $productID); + } + + /* 创建一个测试任务。*/ + function create($productID) + { + $task = fixer::input('post') + ->add('product', $productID) + ->stripTags('name') + ->specialChars('desc') + ->get(); + $this->dao->insert(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck('title,project,build', 'notempty')->exec(); + if(!dao::isError()) return $this->dao->lastInsertID(); + } + + /* 获得某一个产品的测试任务列表。*/ + public function getProductTasks($productID, $orderBy = 'id|desc', $pager = null) + { + return $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName')->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') + ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') + ->where('t1.product')->eq((int)$productID)->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /* 获取一个测试任务的详细信息。*/ + public function getById($taskID) + { + return $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName')->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') + ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') + ->where('t1.id')->eq((int)$taskID)->fetch(); + } + + /* 更新测试任务信息。*/ + public function update($taskID) + { + $task = fixer::input('post') + ->stripTags('name') + ->specialChars('desc') + ->get(); + $this->dao->update(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck('title,project,build', 'notempty')->where('id')->eq($taskID)->exec(); + } + + /* 删除测试任务信息。*/ + public function delete($taskID) + { + $this->dao->delete()->from(TABLE_TESTTASK)->where('id')->eq($taskID)->exec(); + } + + /* 关联用例。*/ + public function linkCase($taskID) + { + foreach($this->post->cases as $key => $caseID) + { + $row->task = $taskID; + $row->case = $caseID; + $row->version = $this->post->versions[$key]; + $row->assignedTo = $this->app->user->account; + $this->dao->replace(TABLE_TASKCASE)->data($row)->exec(); + } + } + + /* 获得任务的用例列表。*/ + public function getCases($taskID) + { + return $this->dao->select('t2.*,t1.*')->from(TABLE_TASKCASE)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->where('t1.task')->eq((int)$taskID) + ->fetchAll(); + } +} diff --git a/module/testtask/view/browse.html.php b/module/testtask/view/browse.html.php new file mode 100644 index 0000000000..0a18aa827f --- /dev/null +++ b/module/testtask/view/browse.html.php @@ -0,0 +1,70 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id: browse.html.php 271 2010-01-09 03:37:02Z wwccss $ + * @link http://www.zentao.cn + */ +?> + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
testtask->browse;?>
+
testtask->create);?>
+
testtask->id;?>testtask->product;?>testtask->project;?>testtask->build;?>testtask->name;?>testtask->begin;?>testtask->end;?>testtask->status;?>action;?>
createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>productName?>projectName?>buildName?>name;?>begin?>end?>testtask->statusList[$task->status];?> + id", $lang->edit); + common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); + common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCase); + ?> +
+
+ diff --git a/module/testtask/view/create.html.php b/module/testtask/view/create.html.php new file mode 100644 index 0000000000..422b5aa931 --- /dev/null +++ b/module/testtask/view/create.html.php @@ -0,0 +1,64 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +?> + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
testtask->create;?>
testtask->project;?>
testtask->build;?>
testtask->begin;?> +
testtask->end;?> +
testtask->status;?>testtask->statusList, '', "class='select-3'");?> +
testtask->name;?> +
testtask->desc;?> +
+
+
+ diff --git a/module/testtask/view/edit.html.php b/module/testtask/view/edit.html.php new file mode 100644 index 0000000000..b881e25c6c --- /dev/null +++ b/module/testtask/view/edit.html.php @@ -0,0 +1,64 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +?> + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
testtask->edit;?>
testtask->project;?>project, 'class=select-3');?>
testtask->build;?>build, 'class=select-3');?>
testtask->begin;?>begin, "class='text-3'");?> +
testtask->end;?>end, "class='text-3'");?> +
testtask->status;?>testtask->statusList, $task->status, "class='select-3'");?> +
testtask->name;?>name, "class='text-1'");?> +
testtask->desc;?>desc, "rows=8 class='area-1'");?> +
+
+
+ diff --git a/module/testtask/view/linkcase.html.php b/module/testtask/view/linkcase.html.php new file mode 100644 index 0000000000..f2a6e97508 --- /dev/null +++ b/module/testtask/view/linkcase.html.php @@ -0,0 +1,73 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package testtask + * @version $Id$ + * @link http://www.zentao.cn + */ +?> + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
testtask->unlinkedCases;?>
testcase->id;?>testcase->pri;?>testcase->title;?>testcase->type;?>testcase->openedBy;?>testcase->status;?>testtask->linkCase . '/' . $lang->testcase->version;?>
createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?> + title . ' ( '; + for($i = $case->version; $i >= 1; $i --) + { + echo html::a($this->createLink('testcase', 'view', "caseID=$case->id&version=$i"), "#$i", '_blank'); + } + echo ')'; + ?> + testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> + + version, 1), range($case->version, 1)), '', 'style=width:50px');?> +
+
+
+ diff --git a/module/testtask/view/view.html.php b/module/testtask/view/view.html.php new file mode 100644 index 0000000000..0667d8e827 --- /dev/null +++ b/module/testtask/view/view.html.php @@ -0,0 +1,93 @@ +. + * + * @copyright Copyright: 2009 Chunsheng Wang + * @author Chunsheng Wang + * @package case + * @version $Id: view.html.php 355 2010-01-29 06:59:40Z wwccss $ + * @link http://www.zentao.cn + */ +?> + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
testtask->view;?>
testtask->project;?>projectName;?>
testtask->build;?>buildName;?>
testtask->begin;?>begin;?> +
testtask->end;?>end;?> +
testtask->status;?>testtask->statusList[$task->status];?> +
testtask->name;?>name;?> +
testtask->desc;?>desc);?> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
testtask->linkedCases;?>
testcase->id;?>testcase->pri;?>testcase->title;?>testcase->type;?>testcase->openedBy;?>testcase->status;?>action;?>
createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?>createLink('testcase', 'view', "caseID=$case->id&version=$case->version"), $case->title, '_blank');?> + testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> + id", $lang->testtask->unlinkCase, 'hiddenwin'); + common::printLink('testtask', 'executecase', "taskID=$task->id&caseid=$case->id", $lang->testtask->executeCase); + ?> +
+
+