From aa4bc30df9029e832bd70b293363671ec1d8aa0b Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 5 May 2023 18:44:28 +0800 Subject: [PATCH] * add unit test. --- module/product/model.php | 2 + .../test/model/getprojectlistbyproduct.php | 31 ++++++-- .../test/model/getprojectstatsbyproduct.php | 79 +++++++++---------- module/product/test/product.class.php | 37 +++++---- module/program/model.php | 7 +- .../test/model/appendstattoprojects.php | 63 +++++++++++++++ module/program/test/model/computeprogress.php | 51 ------------ .../test/model/computeprojecthours.php | 31 ++++++++ 8 files changed, 187 insertions(+), 114 deletions(-) create mode 100755 module/program/test/model/appendstattoprojects.php delete mode 100755 module/program/test/model/computeprogress.php create mode 100755 module/program/test/model/computeprojecthours.php diff --git a/module/product/model.php b/module/product/model.php index 0a6fe6fa2a..ab6b3484e3 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -1115,6 +1115,7 @@ class productModel extends model } /** + * 获取与该产品关联的项目列表。 * Get project list by product. * * @param int $productID @@ -1143,6 +1144,7 @@ class productModel extends model } /** + * 根据产品,获取与该产品关联的项目的统计信息。 * Get project stats by product. * * @param int $productID diff --git a/module/product/test/model/getprojectlistbyproduct.php b/module/product/test/model/getprojectlistbyproduct.php index a5f05cbf15..5ab167822d 100755 --- a/module/product/test/model/getprojectlistbyproduct.php +++ b/module/product/test/model/getprojectlistbyproduct.php @@ -46,8 +46,29 @@ $product->app->user->admin = true; $product->app->moduleName = 'product'; $product->app->methodName = 'project'; -r(count($product->getProjectListByProduct($productID = 0, 'all', '', 'order_desc'))) && p() && e('0'); -r(count($product->getProjectListByProduct($productID = 1, 'all', '', 'order_desc'))) && p() && e('20'); -r(count($product->getProjectListByProduct($productID = 1, 'all', '0', 'order_desc'))) && p() && e('17'); -r(count($product->getProjectListByProduct($productID = 1, 'undone', '', 'order_desc'))) && p() && e('15'); -r(count($product->getProjectListByProduct($productID = 1, 'wait', 'all', 'order_desc'))) && p() && e('5'); +r(count($product->getProjectListByProduct($productID = 0, 'all', '', false, 'order_desc'))) && p() && e('0'); +r(count($product->getProjectListByProduct($productID = 1, 'all', '', false, 'order_desc'))) && p() && e('20'); +r(count($product->getProjectListByProduct($productID = 1, 'all', '0', false, 'order_desc'))) && p() && e('17'); +r(count($product->getProjectListByProduct($productID = 1, 'undone', '', false, 'order_desc'))) && p() && e('15'); +r(count($product->getProjectListByProduct($productID = 1, 'wait', 'all', false, 'order_desc'))) && p() && e('5'); + +$product->app->loadClass('pager', $static = true); +$pager = new pager(0, 50, 1); +r(count($product->getProjectListByProduct($productID = 1, 'all', '', false, 'order_desc', $pager))) && p() && e('20'); + +$pager = new pager(0, 5, 1); +r(count($product->getProjectListByProduct($productID = 1, 'all', '', false, 'order_desc', $pager))) && p() && e('5'); + +$product->app->user->admin = false; +$product->app->user->view->projects = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,48,49,50'; +r(count($product->getProjectListByProduct($productID = 1, 'all', '', true, 'order_desc'))) && p() && e('4'); +r(count($product->getProjectListByProduct($productID = 1, 'all', '0', true, 'order_desc'))) && p() && e('4'); +r(count($product->getProjectListByProduct($productID = 1, 'undone', '', true, 'order_desc'))) && p() && e('2'); +r(count($product->getProjectListByProduct($productID = 1, 'wait', 'all', true, 'order_desc'))) && p() && e('0'); + +$product->app->loadClass('pager', $static = true); +$pager = new pager(0, 50, 1); +r(count($product->getProjectListByProduct($productID = 1, 'all', '', true, 'order_desc', $pager))) && p() && e('4'); + +$pager = new pager(0, 5, 1); +r(count($product->getProjectListByProduct($productID = 1, 'all', '', true, 'order_desc', $pager))) && p() && e('4'); diff --git a/module/product/test/model/getprojectstatsbyproduct.php b/module/product/test/model/getprojectstatsbyproduct.php index 2aa0334415..9ec4b69bbb 100755 --- a/module/product/test/model/getprojectstatsbyproduct.php +++ b/module/product/test/model/getprojectstatsbyproduct.php @@ -3,55 +3,48 @@ include dirname(__FILE__, 5) . "/test/lib/init.php"; include dirname(__FILE__, 2) . '/product.class.php'; +zdTable('product')->gen(50); +zdTable('user')->gen(50); + +$project = zdTable('project'); +$project->PM->range('user2,user3'); +$project->gen(50); + +$task = zdTable('task'); +$task->project->range('1-20'); +$task->gen(100); + +$team = zdTable('team'); +$team->root->range('1-50'); +$team->type->range('project'); +$team->account->range('admin,admin,user1,user1'); +$team->days->range('5'); +$team->hours->range('6,7'); +$team->gen(50); + +$stakeholder = zdTable('stakeholder'); +$stakeholder->objectType->range('project'); +$stakeholder->objectID->range('1-50'); +$stakeholder->user->range('user4,user5'); +$stakeholder->type->range('inside'); +$stakeholder->from->range(''); +$stakeholder->gen(50); + +$projectproduct = zdTable('projectproduct'); +$projectproduct->product->range('1-2'); +$projectproduct->project->range('1-50'); +$projectproduct->gen(50); + /** -title=productModel->getProjectStatsByProduct(); +title=productModel->getProjectStatsByProductTest(); cid=1 pid=1 -测试获取产品1的 browseType为all的信息 >> 项目1;项目11 -测试获取产品1的 browseType为unclosed的信息 >> 0 -测试获取产品1的 browseType为unplan的信息 >> 0 -测试获取产品1的 browseType为allstory的信息 >> 0 -测试获取产品2的 browseType为all的信息 >> 项目2;项目12 -测试获取产品2的 browseType为assignedtome的信息 >> 0 -测试获取产品2的 browseType为openedbyme的信息 >> 0 -测试获取产品2的 browseType为reviewedbyme的信息 >> 0 -测试获取产品3的 browseType为all的信息 >> 项目3;项目13 -测试获取产品3的 browseType为reviewbyme的信息 >> 0 -测试获取产品3的 browseType为closedbyme的信息 >> 0 -测试获取产品3的 browseType为draftstory的信息 >> 0 -测试获取产品4的 browseType为all的信息 >> 项目4;项目14 -测试获取产品4的 browseType为activestory的信息 >> 0 -测试获取产品4的 browseType为changedstory的信息 >> 0 -测试获取产品5的 browseType为all的信息 >> 项目5;项目15 -测试获取产品5的 browseType为willclose的信息 >> 0 -测试获取产品5的 browseType为closedstory的信息 >> 0 -测试获取不存在产品的信息 >> 0 - */ -$productIDList = array('1', '2', '3', '4', '5', '1000001'); -$browseType = array('unclosed', 'unplan', 'allstory', 'assignedtome', 'openedbyme', 'reviewedbyme', 'reviewbyme', 'closedbyme', 'draftstory', 'activestory', 'changedstory', 'willclose', 'closedstory'); - $product = new productTest('admin'); -r($product->getProjectStatsByProductTest($productIDList[0])) && p('11;21') && e('项目1;项目11'); // 测试获取产品1的 browseType为all的信息 -r($product->getProjectStatsByProductTest($productIDList[0], $browseType[0])) && p() && e('0'); // 测试获取产品1的 browseType为unclosed的信息 -r($product->getProjectStatsByProductTest($productIDList[0], $browseType[1])) && p() && e('0'); // 测试获取产品1的 browseType为unplan的信息 -r($product->getProjectStatsByProductTest($productIDList[0], $browseType[2])) && p() && e('0'); // 测试获取产品1的 browseType为allstory的信息 -r($product->getProjectStatsByProductTest($productIDList[1])) && p('12;22') && e('项目2;项目12'); // 测试获取产品2的 browseType为all的信息 -r($product->getProjectStatsByProductTest($productIDList[1], $browseType[3])) && p() && e('0'); // 测试获取产品2的 browseType为assignedtome的信息 -r($product->getProjectStatsByProductTest($productIDList[1], $browseType[4])) && p() && e('0'); // 测试获取产品2的 browseType为openedbyme的信息 -r($product->getProjectStatsByProductTest($productIDList[1], $browseType[5])) && p() && e('0'); // 测试获取产品2的 browseType为reviewedbyme的信息 -r($product->getProjectStatsByProductTest($productIDList[2])) && p('13;23') && e('项目3;项目13'); // 测试获取产品3的 browseType为all的信息 -r($product->getProjectStatsByProductTest($productIDList[2], $browseType[6])) && p() && e('0'); // 测试获取产品3的 browseType为reviewbyme的信息 -r($product->getProjectStatsByProductTest($productIDList[2], $browseType[7])) && p() && e('0'); // 测试获取产品3的 browseType为closedbyme的信息 -r($product->getProjectStatsByProductTest($productIDList[2], $browseType[8])) && p() && e('0'); // 测试获取产品3的 browseType为draftstory的信息 -r($product->getProjectStatsByProductTest($productIDList[3])) && p('14;24') && e('项目4;项目14'); // 测试获取产品4的 browseType为all的信息 -r($product->getProjectStatsByProductTest($productIDList[3], $browseType[9])) && p() && e('0'); // 测试获取产品4的 browseType为activestory的信息 -r($product->getProjectStatsByProductTest($productIDList[3], $browseType[10])) && p() && e('0'); // 测试获取产品4的 browseType为changedstory的信息 -r($product->getProjectStatsByProductTest($productIDList[4])) && p('15;25') && e('项目5;项目15'); // 测试获取产品5的 browseType为all的信息 -r($product->getProjectStatsByProductTest($productIDList[4], $browseType[11])) && p() && e('0'); // 测试获取产品5的 browseType为willclose的信息 -r($product->getProjectStatsByProductTest($productIDList[4], $browseType[12])) && p() && e('0'); // 测试获取产品5的 browseType为closedstory的信息 -r($product->getProjectStatsByProductTest($productIDList[5])) && p() && e('0'); // 测试获取不存在产品的信息 \ No newline at end of file +r($product->getProjectStatsByProductTest($productID = 0, 'all', '', false, 'order_desc')) && p() && e('0'); +r($product->getProjectStatsByProductTest($productID = 1, 'all', '', false, 'order_desc')) && p('11:totalConsumed,totalEstimate,totalLeft,progress,teamCount') && e('15,30,10,60,1'); +r($product->getProjectStatsByProductTest($productID = 1, 'all', '', true, 'order_desc')) && p('17:totalConsumed,totalEstimate,totalLeft,progress,teamCount') && e('45,27,11,80,1'); diff --git a/module/product/test/product.class.php b/module/product/test/product.class.php index d84aff0887..ac8734e644 100644 --- a/module/product/test/product.class.php +++ b/module/product/test/product.class.php @@ -699,28 +699,37 @@ class productTest } /** - * Test get project stats by product. + * 测试 getProjectStatsByProduct 方法。 + * Test getProjectStatsByProduct method. * - * @param int $productID - * @param string $browseType + * @param int $productID + * @param string $browseType + * @param string $branch + * @param bool $involved + * @param string $order + * @param object|null $pager * @access public * @return array */ - public function getProjectStatsByProductTest($productID, $browseType = 'all') + public function getProjectStatsByProductTest(int $productID, string $browseType = 'all', string $branch = '', bool $involved = false, string $orderBy = 'order_desc', object|null $pager = null): array { - $objects = $this->objectModel->getProjectStatsByProduct($productID, $browseType); + $objects = $this->objectModel->getProjectStatsByProduct($productID, $browseType, $branch, $involved, $orderBy, $pager); - foreach($objects as $object) $projects[$object->id] = $object->name; - - - if(dao::isError()) + $projects = array(); + foreach($objects as $object) { - return dao::getError(); - } - else - { - return isset($projects) ? $projects : array(); + $project = new stdclass(); + $project->id = $object->id; + $project->totalConsumed = $object->hours->totalConsumed; + $project->totalEstimate = $object->hours->totalEstimate; + $project->totalLeft = $object->hours->totalLeft; + $project->progress = $object->hours->progress; + $project->teamCount = $object->teamCount; + $projects[$project->id] = $project; } + + if(dao::isError()) return dao::getError(); + return $projects; } /** diff --git a/module/program/model.php b/module/program/model.php index 40b7594511..61234a2d5d 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -526,6 +526,8 @@ class programModel extends model */ public function computeProjectHours(array $tasks): array { + if(empty($tasks)) return array(); + $hours = array(); foreach($tasks as $projectID => $projectTasks) { @@ -540,7 +542,7 @@ class programModel extends model { $hour->totalConsumed += $task->consumed; $hour->totalEstimate += $task->estimate; - if($task->status != 'cancel' and $task->status != 'closed') $hour->totalLeft += $task->left; + if(strpos('|cancel|closed|done|', "|{$task->status}|") === false) $hour->totalLeft += $task->left; } $hours[$projectID] = $hour; } @@ -571,6 +573,9 @@ class programModel extends model */ public function appendStatToProjects(array $projects, string $appendFields = '', array $data = array()): array { + if(empty($projects)) return array(); + if(empty($appendFields) or empty($data)) return $projects; + $appendFields = explode(',', $appendFields); $emptyHour = json_decode(json_encode(array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0))); /* Process projects. */ diff --git a/module/program/test/model/appendstattoprojects.php b/module/program/test/model/appendstattoprojects.php new file mode 100755 index 0000000000..7b1fbb9816 --- /dev/null +++ b/module/program/test/model/appendstattoprojects.php @@ -0,0 +1,63 @@ +#!/usr/bin/env php +gen(50); + +$task = zdTable('task'); +$task->project->range('1-20'); +$task->gen(100); + +/** + +title=测试 programModel::create(); +cid=1 +pid=1 + +*/ + +global $tester; +$tester->loadModel('program'); + +$projectID = 11; +$hour = new stdclass(); +$hour->totalConsumed = 15; +$hour->totalEstimate = 30; +$hour->totalLeft = 10; +$hour->progress = 60; +$hours[$projectID] = $hour; + +$projects = $tester->program->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetchAll('id'); +$teams = $tester->program->dao->select('t1.root,t1.account')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account') + ->where('t1.root')->eq($projectID) + ->andWhere('t1.type')->eq('project') + ->andWhere('t2.deleted')->eq(0) + ->fetchGroup('root', 'account'); +$leftTasks = $tester->program->dao->select('t2.parent as project, count(*) as tasks')->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.project')->eq($projectID) + ->andWhere('t1.status')->notIn('cancel,closed') + ->groupBy('t2.parent') + ->fetchAll('project'); + + +r($tester->program->appendStatToProjects(array())) && p() && e('0'); //不传入任何数据 +r($tester->program->appendStatToProjects($projects)) && p('11:id') && e('11'); //只传入项目数据 + +$stats = $tester->program->appendStatToProjects($projects, 'hours'); +r(isset($stats[$projectID]->hours)) && p() && e('0'); //只传入项目数据和hours追加字段 +$stats = $tester->program->appendStatToProjects($projects, 'teamCount'); +r(isset($stats[$projectID]->teamCount)) && p() && e('0'); //只传入项目数据和teamCount追加字段 +$stats = $tester->program->appendStatToProjects($projects, 'teamMembers'); +r(isset($stats[$projectID]->teamMembers)) && p() && e('0'); //只传入项目数据和teamMembers追加字段 +$stats = $tester->program->appendStatToProjects($projects, 'leftTasks'); +r(isset($stats[$projectID]->leftTasks)) && p() && e('0'); //只传入项目数据和leftTasks追加字段 + +$stats = $tester->program->appendStatToProjects($projects, 'hours,teamCount,teamMembers,leftTasks', array('hours' => $hours, 'teams' => $teams, 'leftTasks' => $leftTasks)); +$stat = $stats[$projectID]; +r(isset($stat->hours)) && p() && e('1'); //正常传入数据,检查hours字段 +r(isset($stat->teamCount)) && p() && e('1'); //正常传入数据,检查teamCount字段 +r(isset($stat->teamMembers)) && p() && e('1'); //正常传入数据,检查teamMembers字段 +r(isset($stat->leftTasks)) && p() && e('1'); //正常传入数据,检查leftTasks字段 + diff --git a/module/program/test/model/computeprogress.php b/module/program/test/model/computeprogress.php deleted file mode 100755 index c8332362f3..0000000000 --- a/module/program/test/model/computeprogress.php +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env php -> 13 -传入任务数组,返回计算后的总预计 >> 15 -传入任务数组,返回计算后的总剩余 >> 7 -传入任务数组,返回计算后的总工时 >> 20 -传入任务数组,返回计算后的进度 >> 65 - -*/ - -global $tester; -$tester->loadModel('program'); -$task1 = new stdclass(); -$task1->consumed = 2; -$task1->left = 2; -$task1->estimate = 2; -$task1->status = 'active'; - -$task2 = new stdclass(); -$task2->consumed = 4; -$task2->left = 5; -$task2->estimate = 6; -$task2->status = 'active'; - -$task3 = new stdclass(); -$task3->consumed = 7; -$task3->left = 7; -$task3->estimate = 7; -$task3->status = 'closed'; - -$tasks[] = $task1; -$tasks[] = $task2; -$tasks[] = $task3; - -$projectTasks[1] = $tasks; - -$hours = $tester->program->computeProgress($projectTasks); - -r($hours) && p('1:totalConsumed') && e('13'); // 传入任务数组,返回计算后的总消耗 -r($hours) && p('1:totalEstimate') && e('15'); // 传入任务数组,返回计算后的总预计 -r($hours) && p('1:totalLeft') && e('7'); // 传入任务数组,返回计算后的总剩余 -r($hours) && p('1:totalReal') && e('20'); // 传入任务数组,返回计算后的总工时 -r($hours) && p('1:progress') && e('65'); // 传入任务数组,返回计算后的进度 \ No newline at end of file diff --git a/module/program/test/model/computeprojecthours.php b/module/program/test/model/computeprojecthours.php new file mode 100755 index 0000000000..90b8161140 --- /dev/null +++ b/module/program/test/model/computeprojecthours.php @@ -0,0 +1,31 @@ +#!/usr/bin/env php +gen(50); + +$task = zdTable('task'); +$task->project->range('1-20'); +$task->gen(100); + +/** + +title=测试 programModel::create(); +cid=1 +pid=1 + +*/ + +global $tester; +$tester->loadModel('program'); +$tasks = $tester->program->dao->select('id, project, estimate, consumed, `left`, status, closedReason, execution') + ->from(TABLE_TASK) + ->where('project')->eq('11') + ->andWhere('parent')->lt(1) + ->andWhere('deleted')->eq(0) + ->fetchGroup('project', 'id'); + +$hours = $tester->program->computeProjectHours($tasks); + +r($tester->program->computeProjectHours(array())) && p() && e('0'); +r($tester->program->computeProjectHours($tasks)) && p('11:totalConsumed,totalEstimate,totalLeft,progress') && e('15,30,10,60');