387 lines
14 KiB
PHP
387 lines
14 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
/**
|
|
* The model file of testreport module of ZenTaoPMS.
|
|
*
|
|
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(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 Yidong Wang <yidong@cnezsoft.com>
|
|
* @package testreport
|
|
* @version $Id$
|
|
* @link https://www.zentao.net
|
|
*/
|
|
class testreportModel extends model
|
|
{
|
|
/**
|
|
* 创建一个测试报告。
|
|
* Create a test report.
|
|
*
|
|
* @param object $testreport
|
|
* @access public
|
|
* @return int|false
|
|
*/
|
|
public function create(object $testreport): int|false
|
|
{
|
|
$this->dao->insert(TABLE_TESTREPORT)->data($testreport)->autocheck()
|
|
->batchCheck($this->config->testreport->create->requiredFields, 'notempty')
|
|
->batchCheck('begin,end', 'notempty')
|
|
->check('end', 'ge', $testreport->begin)
|
|
->exec();
|
|
|
|
if(dao::isError()) return false;
|
|
|
|
$reportID = $this->dao->lastInsertID();
|
|
$this->loadModel('file')->updateObjectID($this->post->uid, $reportID, 'testreport');
|
|
$this->file->saveUpload('testreport', $reportID);
|
|
|
|
return $reportID;
|
|
}
|
|
|
|
/**
|
|
* 更新一个测试报告。
|
|
* Update a report.
|
|
*
|
|
* @param object $report
|
|
* @param object $oldReport
|
|
* @access public
|
|
* @return array|bool
|
|
*/
|
|
public function update(object $report, object $oldReport): array|bool
|
|
{
|
|
$this->dao->update(TABLE_TESTREPORT)->data($report, 'deleteFiles,renameFiles,files')->autocheck()
|
|
->batchCheck($this->config->testreport->edit->requiredFields, 'notempty')
|
|
->batchCheck('begin,end', 'notempty')
|
|
->check('end', 'ge', $report->begin)
|
|
->where('id')->eq($report->id)
|
|
->exec();
|
|
|
|
if(dao::isError()) return false;
|
|
|
|
$this->loadModel('file')->processFileDiffsForObject('testreport', $oldReport, $report);
|
|
|
|
return common::createChanges($oldReport, $report);
|
|
}
|
|
|
|
/**
|
|
* 通过 id 获取测试报告。
|
|
* Get report by id.
|
|
*
|
|
* @param int $reportID
|
|
* @access public
|
|
* @return object|false
|
|
*/
|
|
public function getById(int $reportID): object|false
|
|
{
|
|
$report = $this->dao->select('*')->from(TABLE_TESTREPORT)->where('id')->eq($reportID)->fetch();
|
|
if(!$report) return false;
|
|
|
|
$report = $this->loadModel('file')->replaceImgURL($report, 'report');
|
|
$report->files = $this->file->getByObject('testreport', $reportID);
|
|
return $report;
|
|
}
|
|
|
|
/**
|
|
* 获取报告列表。
|
|
* Get report list.
|
|
*
|
|
* @param int $objectID
|
|
* @param string $objectType
|
|
* @param int $extra
|
|
* @param string $orderBy
|
|
* @param object $pager
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getList(int $objectID, string $objectType, int $extra = 0, string $orderBy = 'id_desc', ?object $pager = null): array
|
|
{
|
|
if(common::isTutorialMode()) return $this->loadModel('tutorial')->getTestReports();
|
|
|
|
return $this->dao->select('*')->from(TABLE_TESTREPORT)
|
|
->where('deleted')->eq(0)
|
|
->beginIF($objectType == 'execution')->andWhere('execution')->eq($objectID)->fi()
|
|
->beginIF($objectType == 'project')->andWhere('project')->eq($objectID)->fi()
|
|
->beginIF($objectType == 'product' && $extra)->andWhere('objectID')->eq($extra)->andWhere('objectType')->eq('testtask')->fi()
|
|
->beginIF($objectType == 'product' && !$extra)->andWhere('product')->eq($objectID)->fi()
|
|
->orderBy($orderBy)
|
|
->page($pager)
|
|
->fetchAll('id', false);
|
|
}
|
|
|
|
/**
|
|
* 获取测试单的用例列表。
|
|
* Get task cases.
|
|
*
|
|
* @param array $tasks
|
|
* @param string $begin
|
|
* @param string $end
|
|
* @param string $idList
|
|
* @param object $pager
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getTaskCases(array $tasks, string $begin, string $end, string $idList = '', ?object $pager = null): array
|
|
{
|
|
$cases = $this->dao->select('t2.*, t1.task, t1.assignedTo, t1.status, t1.lastRunDate AS maxRunDate')->from(TABLE_TESTRUN)->alias('t1')
|
|
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
|
|
->where('t1.task')->in(array_keys($tasks))
|
|
->andWhere('t2.deleted')->eq('0')
|
|
->beginIF($idList)->andWhere('t2.id')->in($idList)->fi()
|
|
->page($pager)
|
|
->fetchGroup('task', 'id');
|
|
|
|
$results = $this->dao->select('t1.*, t2.task')->from(TABLE_TESTRESULT)->alias('t1')
|
|
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.run = t2.id')
|
|
->where('t2.task')->in(array_keys($tasks))
|
|
->andWhere('t1.date')->ge($begin)
|
|
->andWhere('t1.date')->le($end . " 23:59:59")
|
|
->orderBy('date')
|
|
->fetchGroup('task', 'case');
|
|
|
|
foreach($cases as $taskID => $caseList)
|
|
{
|
|
$taskResults = zget($results, $taskID, array());
|
|
|
|
foreach($caseList as $caseID => $case)
|
|
{
|
|
$result = zget($taskResults, $caseID, '');
|
|
|
|
$case->lastRunner = $result ? $result->lastRunner : '';
|
|
$case->lastRunDate = $result ? $result->date : '';
|
|
$case->lastRunResult = $result ? $result->caseResult : '';
|
|
$case->status = ($result && $result->caseResult == 'blocked') ? 'blocked' : 'normal';
|
|
}
|
|
}
|
|
|
|
return $cases;
|
|
}
|
|
|
|
/**
|
|
* 获取测试报告的用例列表。
|
|
* Get case id list.
|
|
*
|
|
* @param int $reportID
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getCaseIdList(int $reportID): array
|
|
{
|
|
return $this->dao->select('`case`')->from(TABLE_TESTREPORT)->alias('t1')
|
|
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.tasks = t2.task')
|
|
->leftJoin(TABLE_CASE)->alias('t3')->on('t2.case = t3.id')
|
|
->where('t1.id')->eq($reportID)
|
|
->andWhere('t1.deleted')->eq('0')
|
|
->andWhere('t3.deleted')->eq('0')
|
|
->fetchPairs('case');
|
|
}
|
|
|
|
/**
|
|
* 获取报告概况。
|
|
* Get report summary.
|
|
*
|
|
* @param array $tasks
|
|
* @param array $cases
|
|
* @param string $begin
|
|
* @param string $end
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function getResultSummary(array $tasks, array $cases, string $begin, string $end): string
|
|
{
|
|
$caseCount = 0;
|
|
$caseIdList = array();
|
|
foreach($cases as $caseList)
|
|
{
|
|
$caseCount += count($caseList);
|
|
$caseIdList = array_merge($caseIdList, array_keys($caseList));
|
|
}
|
|
|
|
$results = $this->dao->select('t1.*')->from(TABLE_TESTRESULT)->alias('t1')
|
|
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.run = t2.id')
|
|
->where('t2.task')->in(array_keys($tasks))
|
|
->andWhere('t1.`case`')->in($caseIdList)
|
|
->andWhere('t1.date')->ge($begin)
|
|
->andWhere('t1.date')->le($end . " 23:59:59")
|
|
->orderBy('date')
|
|
->fetchAll('id', false);
|
|
|
|
$failResults = 0;
|
|
$runCasesResults = array();
|
|
foreach($results as $result) $runCasesResults[$result->run] = $result->caseResult;
|
|
foreach($runCasesResults as $lastResult) if($lastResult != 'pass') $failResults++;
|
|
|
|
return sprintf($this->lang->testreport->caseSummary, $caseCount, count($runCasesResults), count($results), $failResults);
|
|
}
|
|
|
|
/**
|
|
* 获取测试报告的用例执行结果。
|
|
* Get per run result for testreport.
|
|
*
|
|
* @param array $tasks
|
|
* @param array|string $cases
|
|
* @param string $begin
|
|
* @param string $end
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function getPerCaseResult4Report(array $tasks, array|string $cases, string $begin, string $end): array
|
|
{
|
|
/* Get case result. */
|
|
$datas = $this->dao->select("t1.caseResult AS name, COUNT('t1.*') AS value")->from(TABLE_TESTRESULT)->alias('t1')
|
|
->leftJoin(TABLE_TESTRUN)->alias('t2')
|
|
->on('t1.run = t2.id')
|
|
->where('t2.task')->in(array_keys($tasks))
|
|
->andwhere('t1.date = t2.lastRunDate')
|
|
->andWhere('t1.`case`')->in($cases)
|
|
->andWhere('t1.date')->ge($begin)
|
|
->andWhere('t1.date')->le($end . " 23:59:59")
|
|
->groupBy('t1.caseResult')
|
|
->orderBy('value DESC')
|
|
->fetchAll('name');
|
|
|
|
if(!$datas) return array();
|
|
|
|
/* Set case result language item. */
|
|
$this->app->loadLang('testcase');
|
|
foreach($datas as $result => $data) $data->name = isset($this->lang->testcase->resultList[$result]) ? $this->lang->testcase->resultList[$result] : $this->lang->testtask->unexecuted;
|
|
|
|
return $datas;
|
|
}
|
|
|
|
/**
|
|
* 获取测试报告的用例执行人。
|
|
* Get per case runner for testreport.
|
|
*
|
|
* @param array $tasks
|
|
* @param array|string $cases
|
|
* @param string $begin
|
|
* @param string $end
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getPerCaseRunner4Report(array $tasks, array|string $cases, string $begin, string $end): array
|
|
{
|
|
/* Get the last runner and the number of runs. */
|
|
$datas = $this->dao->select("t1.lastRunner AS name, COUNT('t1.*') AS value")->from(TABLE_TESTRESULT)->alias('t1')
|
|
->leftJoin(TABLE_TESTRUN)->alias('t2')
|
|
->on('t1.run= t2.id')
|
|
->where('t2.task')->in(array_keys($tasks))
|
|
->andwhere('t1.date = t2.lastRunDate')
|
|
->andWhere('t1.`case`')->in($cases)
|
|
->andWhere('t1.date')->ge($begin)
|
|
->andWhere('t1.date')->le($end . " 23:59:59")
|
|
->groupBy('t1.lastRunner')
|
|
->orderBy('value DESC')
|
|
->fetchAll('name');
|
|
|
|
if(!$datas) return array();
|
|
|
|
/* Set the realname of the last runner. */
|
|
$users = $this->loadModel('user')->getPairs('noclosed|noletter');
|
|
foreach($datas as $result => $data) $data->name = $result ? zget($users, $result, $result) : $this->lang->testtask->unexecuted;
|
|
|
|
return $datas;
|
|
}
|
|
|
|
/**
|
|
* 为测试报告获取 bugs。
|
|
* Get bugs for test
|
|
*
|
|
* @param array|bool $builds
|
|
* @param int|array $product
|
|
* @param string $begin
|
|
* @param string $end
|
|
* @param string $type
|
|
* @access public
|
|
* @return array|false
|
|
*/
|
|
public function getBugs4Test(array|bool $builds, int|array $product, string $begin, string $end, string $type = 'build'): array|false
|
|
{
|
|
$bugIdList = '';
|
|
if(is_array($builds))
|
|
{
|
|
$childBuilds = $this->getChildBuilds($builds);
|
|
foreach($builds as $build) $bugIdList .= $build->bugs . ',';
|
|
foreach($childBuilds as $childBuild) $bugIdList .= $childBuild->bugs . ',';
|
|
}
|
|
|
|
$bugIdList = array_unique(array_filter(explode(',', $bugIdList)));
|
|
return $this->dao->select('*')->from(TABLE_BUG)->where('deleted')->eq(0)
|
|
->andWhere('product')->in($product)
|
|
->andWhere('openedDate')->lt("{$begin} 23:59:59")
|
|
->beginIF(is_array($builds) && $type == 'build')->andWhere('id')->in($bugIdList)->fi()
|
|
->beginIF(!is_array($builds) && $type == 'build')->andWhere("(resolvedBuild = 'trunk' and resolvedDate >= '{$begin}' and resolvedDate <= '{$end} 23:59:59')")->fi()
|
|
->beginIF(in_array($type, array('project', 'execution')))->andWhere('id')->in($bugIdList)->fi()
|
|
->fetchAll('id', false);
|
|
}
|
|
|
|
/**
|
|
* 获取测试报告的需求。
|
|
* Get stories for test.
|
|
*
|
|
* @param array $builds
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getStories4Test(array $builds): array
|
|
{
|
|
$storyIdList = '';
|
|
$childBuilds = $this->getChildBuilds($builds);
|
|
foreach($builds as $build) $storyIdList .= $build->stories . ',';
|
|
foreach($childBuilds as $childBuild) $storyIdList .= $childBuild->stories . ',';
|
|
|
|
$storyIdList = array_unique(array_filter(explode(',', $storyIdList)));
|
|
return $this->dao->select('*')->from(TABLE_STORY)->where('deleted')->eq('0')->andWhere('id')->in($storyIdList)->fetchAll('id', false);
|
|
}
|
|
|
|
/**
|
|
* 获取测试报告键对。
|
|
* Get pairs.
|
|
*
|
|
* @param int $productID
|
|
* @param int $appendID
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getPairs(int $productID = 0, int $appendID = 0): array
|
|
{
|
|
return $this->dao->select('id,title')->from(TABLE_TESTREPORT)
|
|
->where('deleted')->eq(0)
|
|
->beginIF($productID)->andWhere('product')->eq($productID)->fi()
|
|
->beginIF($appendID)->orWhere('id')->eq($appendID)->fi()
|
|
->orderBy('id_desc')
|
|
->fetchPairs();
|
|
}
|
|
|
|
/**
|
|
* 判断操作是否可以点击。
|
|
* Judge an action is clickable or not.
|
|
*
|
|
* @param object $report
|
|
* @param string $action
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isClickable(object $report, string $action): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get child builds.
|
|
*
|
|
* @param array $builds
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getChildBuilds(array $builds): array
|
|
{
|
|
$childBuildIDList = '';
|
|
foreach($builds as $build) $childBuildIDList .= $build->builds . ',';
|
|
|
|
$childBuildIDList = array_unique(array_filter(explode(',', $childBuildIDList)));
|
|
if(empty($childBuildIDList)) return array();
|
|
|
|
return $this->dao->select('id,name,bugs,stories')->from(TABLE_BUILD)->where('id')->in($childBuildIDList)->fetchAll('id');
|
|
}
|
|
}
|