* Refactor testcase::importToLib, and add testcaseTao::doUpdate, add unit test.

This commit is contained in:
liumengyi
2023-09-06 10:28:11 +08:00
parent 944eea4293
commit ac8377c841
7 changed files with 373 additions and 106 deletions
+9 -2
View File
@@ -1211,17 +1211,24 @@ class testcase extends control
}
/**
* 导入用例到用例库。
* Import cases to library.
*
* @param int $caseID
* @access public
* @return void
*/
public function importToLib($caseID = 0)
public function importToLib(int $caseID = 0)
{
if(!empty($_POST))
{
$this->testcase->importToLib($caseID);
$libID = $this->post->lib;
if(empty($libID)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->testcase->caselib)));
list($cases, $steps, $files) = $this->testcaseZen->buildDataForImportToLib($caseID, $libID);
$this->testcase->importToLib($cases, $steps, $files);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(!empty($caseID)) return $this->send(array('result' => 'success', 'message' => $this->lang->importSuccess, 'closeModal' => true));
return $this->send(array('result' => 'success', 'message' => $this->lang->importSuccess, 'load' => true, 'closeModal' => true));
+29 -103
View File
@@ -40,8 +40,6 @@ class testcaseModel extends model
*/
public function create(object $case): bool|int
{
if(empty($case->product)) $this->config->testcase->create->requiredFields = str_replace('story', '', $this->config->testcase->create->requiredFields);
/* 插入测试用例。 */
/* Insert testcase. */
$this->testcaseTao->doCreate($case);
@@ -723,17 +721,7 @@ class testcaseModel extends model
*/
public function update(object $case, object $oldCase, array $testtasks = array()): bool|array
{
/* Remove the require field named story when the case is a lib case.*/
$requiredFields = $this->config->testcase->edit->requiredFields;
if($oldCase->lib != 0) $requiredFields = str_replace(',story,', ',', ",$requiredFields,");
$this->dao->update(TABLE_CASE)->data($case, 'deleteFiles,uid,stepChanged,comment,steps,expects,stepType,linkBug')
->autoCheck()
->batchCheck($requiredFields, 'notempty')
->checkFlow()
->where('id')->eq((int)$case->id)
->exec();
$this->testcaseTao->doUpdate($case);
if(dao::isError()) return false;
$this->testcaseTao->updateCase2Project($oldCase, $case);
@@ -1289,118 +1277,56 @@ class testcaseModel extends model
}
/**
* 导入测试用例到用例库。
* Import cases to lib.
*
* @param int $caseIdList
* @param array $cases
* @param array $steps
* @param array $files
* @access public
* @return void
* @return bool
*/
public function importToLib($caseIdList = 0)
public function importToLib(array $cases, array $steps, array $files): bool
{
if(empty($caseIdList)) $caseIdList = $this->post->caseIdList;
$caseIdList = explode(',' , $caseIdList);
$libID = $this->post->lib;
if(empty($libID)) return dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->testcase->caselib);
$this->loadModel('action');
$cases = $this->dao->select('*')->from(TABLE_CASE)->where('deleted')->eq(0)->andWhere('id')->in($caseIdList)->fetchAll('id');
$caseSteps = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->in($caseIdList)->orderBy('id')->fetchGroup('case');
$caseFiles = $this->dao->select('*')->from(TABLE_FILE)->where('objectID')->in($caseIdList)->andWhere('objectType')->eq('testcase')->fetchGroup('objectID', 'id');
$libCases = $this->loadModel('caselib')->getLibCases($libID, 'all');
$libFiles = $this->dao->select('*')->from(TABLE_FILE)->where('objectID')->in(array_keys($libCases))->andWhere('objectType')->eq('testcase')->fetchGroup('objectID', 'id');
$libCases = $this->dao->select('*')->from(TABLE_CASE)->where('lib')->eq($libID)->andWhere('product')->eq(0)->andWhere('deleted')->eq('0')->fetchGroup('fromCaseID', 'id');
$maxOrder = $this->dao->select('max(`order`) as maxOrder')->from(TABLE_CASE)->where('deleted')->eq(0)->fetch('maxOrder');
$maxModuleOrder = $this->dao->select('max(`order`) as maxOrder')->from(TABLE_MODULE)->where('deleted')->eq(0)->fetch('maxOrder');
foreach($cases as $caseID => $case)
foreach($cases as $case)
{
$libCase = new stdclass();
$libCase->lib = $libID;
$libCase->title = $case->title;
$libCase->precondition = $case->precondition;
$libCase->keywords = $case->keywords;
$libCase->pri = $case->pri;
$libCase->type = $case->type;
$libCase->stage = $case->stage;
$libCase->status = $case->status;
$libCase->fromCaseID = $case->id;
$libCase->fromCaseVersion = $case->version;
$libCase->order = ++ $maxOrder;
$libCase->module = empty($case->module) ? 0 : $this->importCaseRelatedModules($libID, $case->module, $maxModuleOrder);
if(empty($libCases[$caseID]))
/* 如果用例没有 ID,插入用例。 */
/* If case id is not exist, insert it. */
if(!isset($case->id))
{
$libCase->openedBy = $this->app->user->account;
$libCase->openedDate = helper::now();
$this->dao->insert(TABLE_CASE)->data($libCase)->autoCheck()->exec();
if(!dao::isError()) $libCaseID = $this->dao->lastInsertID();
$this->action->create('case', $libCaseID, 'tolib', '', $caseID);
$this->testcaseTao->doCreate($case);
if(!dao::isError())
{
$caseID = $this->dao->lastInsertID();
$this->action->create('case', $caseID, 'tolib', '', $case->fromCaseID);
}
}
/* 如果用例有 ID,更新用例。 */
/* If case id is exist, update it. */
else
{
$libCaseList = array_keys($libCases[$caseID]);
$libCaseID = $libCaseList[0];
$caseID = $case->id;
$this->testcaseTao->doUpdate($case);
$this->action->create('case', $caseID, 'updatetolib', '', $case->fromCaseID);
$libCase->lastEditedBy = $this->app->user->account;
$libCase->lastEditedDate = helper::now();
$libCase->version = (int)$libCases[$caseID][$libCaseID]->version + 1;
$this->dao->update(TABLE_CASE)->data($libCase)->autoCheck()->where('id')->eq((int)$libCaseID)->exec();
$this->dao->delete()->from(TABLE_CASESTEP)->where('`case`')->eq($caseID)->exec();
$this->action->create('case', $libCaseID, 'updatetolib', '', $caseID);
$this->dao->delete()->from(TABLE_CASESTEP)->where('`case`')->eq($libCaseID)->exec();
$removeFiles = zget($libFiles, $libCaseID, array());
$this->dao->delete()->from(TABLE_FILE)->where('`objectID`')->eq($libCaseID)->andWhere('objectType')->eq('testcase')->exec();
$removeFiles = $this->dao->select('*')->from(TABLE_FILE)->where('`objectID`')->eq($caseID)->andWhere('objectType')->eq('testcase')->fetchAll('id');
$this->dao->delete()->from(TABLE_FILE)->where('`objectID`')->eq($caseID)->andWhere('objectType')->eq('testcase')->exec();
foreach($removeFiles as $fileID => $file)
{
if(empty($file->pathname)) continue;
$filePath = pathinfo($file->pathname, PATHINFO_BASENAME);
$datePath = substr($file->pathname, 0, 6);
$filePath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . "{$datePath}/" . $filePath;
unlink($filePath);
}
}
if(!dao::isError())
{
if(isset($caseSteps[$caseID]))
{
foreach($caseSteps[$caseID] as $index => $step)
{
if($step->version != $case->version) continue;
$oldStepID = $step->id;
$step->case = $libCaseID;
$step->version = zget($libCase, 'version', '0');
unset($step->id);
$this->dao->insert(TABLE_CASESTEP)->data($step)->exec();
}
}
$oldFiles = zget($caseFiles, $caseID, array());
foreach($oldFiles as $fileID => $file)
{
$originName = pathinfo($file->pathname, PATHINFO_FILENAME);
$datePath = substr($file->pathname, 0, 6);
$originFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . "{$datePath}/" . $originName;
$copyName = $originName . 'copy' . $libCaseID;
$copyFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . "{$datePath}/" . $copyName;
copy($originFile, $copyFile);
$newFileName = $file->pathname;
$newFileName = str_replace('.', "copy$libCaseID.", $newFileName);
$file->pathname = $newFileName;
$file->objectID = $libCaseID;
$file->addedBy = $this->app->user->account;
$file->addedDate = helper::now();
$file->downloads = 0;
unset($file->id);
$this->dao->insert(TABLE_FILE)->data($file)->exec();
}
}
$this->testcaseTao->importSteps($caseID, zget($steps, $case->fromCaseID, array()));
$this->testcaseTao->importFiles($caseID, zget($files, $case->fromCaseID, array()));
}
return !dao::isError();
}
/**
+43 -1
View File
@@ -229,7 +229,7 @@ class testcaseTao extends testcaseModel
*/
protected function getRelatedFiles(array $caseIdList): array
{
return $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('testcase')->andWhere('objectID')->in($caseIdList)->andWhere('extra')->ne('editor')->fetchGroup('objectID');
return $this->dao->select('*')->from(TABLE_FILE)->where('objectType')->eq('testcase')->andWhere('objectID')->in($caseIdList)->andWhere('extra')->ne('editor')->fetchGroup('objectID');
}
/**
@@ -242,6 +242,9 @@ class testcaseTao extends testcaseModel
*/
protected function doCreate(object $case): bool
{
if(empty($case->product)) $this->config->testcase->create->requiredFields = str_replace('story', '', $this->config->testcase->create->requiredFields);
if(!empty($case->lib)) $this->config->testcase->create->requiredFields = str_replace('product', '', $this->config->testcase->create->requiredFields);
$this->dao->insert(TABLE_CASE)->data($case, 'steps,expects,files,labels,stepType,needReview,scriptFile,scriptName')
->autoCheck()
->batchCheck($this->config->testcase->create->requiredFields, 'notempty')
@@ -250,6 +253,29 @@ class testcaseTao extends testcaseModel
return !dao::isError();
}
/**
* 更新一个测试用例。
* Update a test case.
*
* @param object $case
* @access protected
* @return bool
*/
protected function doUpdate(object $case): bool
{
/* Remove the require field named story when the case is a lib case.*/
$requiredFields = $this->config->testcase->edit->requiredFields;
if(!empty($case->lib)) $requiredFields = str_replace(',story,', ',', ",$requiredFields,");
$this->dao->update(TABLE_CASE)->data($case, 'deleteFiles,uid,stepChanged,comment,steps,expects,stepType,linkBug')
->autoCheck()
->batchCheck($requiredFields, 'notempty')
->checkFlow()
->where('id')->eq((int)$case->id)
->exec();
return !dao::isError();
}
/*
* 处理用例和项目的关系。
* Deal with the relationship between the case and project when edit the case.
@@ -430,6 +456,22 @@ class testcaseTao extends testcaseModel
/* Insert files. */
foreach($files as $fileID => $file)
{
if(isset($file->oldpathname))
{
if(!empty($file->oldpathname))
{
$originName = pathinfo($file->oldpathname, PATHINFO_FILENAME);
$datePath = substr($file->oldpathname, 0, 6);
$originFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . "{$datePath}/" . $originName;
$copyName = $originName . 'copy' . $caseID;
$copyFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . "{$datePath}/" . $copyName;
copy($originFile, $copyFile);
}
unset($file->oldpathname);
}
$file->objectID = $caseID;
$file->addedBy = $this->app->user->account;
$file->addedDate = helper::now();
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/testcase.class.php';
zdTable('case')->gen('20');
zdTable('file')->config('casefile')->gen('20');
zdTable('casestep')->config('casestep')->gen('20');
zdTable('user')->gen('1');
su('admin');
/**
title=测试 testcaseTao->importToLib();
cid=1
pid=1
*/
$testcase = new testcaseTest();
$caseIdList = array(array(1, 2), array(3, 4), array(100));
r($testcase->importToLibTest($caseIdList[0])) && p() && e('1: 21,22,23,24,25,26,27,28,29,30,31,32 21,22; 2: 33 23,24;'); // 测试将case id 1,2 导入到用例库
r($testcase->importToLibTest($caseIdList[1])) && p() && e('3: 34 25,26; 4: 35 27,28;'); // 测试将case id 3,4 导入到用例库
r($testcase->importToLibTest($caseIdList[2])) && p() && e('0'); // 测试将不存在的case id 100 导入到用例库
r($testcase->importToLibTest($caseIdList[0])) && p() && e('1: 36,37,38,39,40,41,42,43,44,45,46,47 29,30; 2: 48 31,32;'); // 测试重复将case id 1,2 导入到用例库
r($testcase->importToLibTest($caseIdList[1])) && p() && e('3: 49 33,34; 4: 50 35,36;'); // 测试重复将case id 3,4 导入到用例库
r($testcase->importToLibTest($caseIdList[2])) && p() && e('0'); // 测试重复将不存在的case id 100 导入到用例库
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/testcase.class.php';
su('admin');
/**
title=测试 testcaseModel->doUpdate();
timeout=0
cid=1
*/
$testcaseIdList = array(1, 2, 3);
$title = array('title' => '修改后的用例');
$type = array('type' => 'install');
$pri = array('pri' => '1');
$testcase = new testCaseTest();
r($testcase->doUpdateTest($testcaseIdList[0], $title)) && p('title,type,pri') && e('修改后的用例,feature,3'); // 测试更新用例名称
r($testcase->doUpdateTest($testcaseIdList[1], $type)) && p('title,type,pri') && e('测试创建测试用例2,install,1'); // 测试更新用例类型
r($testcase->doUpdateTest($testcaseIdList[2], $pri)) && p('title,type,pri') && e('测试创建测试用例3,feature,1'); // 测试更新用例优先级
+128
View File
@@ -1003,4 +1003,132 @@ class testcaseTest
$caseID = $tester->dao->lastInsertID();
return $this->objectModel->fetchBaseInfo($caseID);
}
/**
* 测试更新一个测试用例。
* Test update a case.
*
* @param int $caseID
* @param array $param
* @access public
* @return bool|array|object
*/
public function doUpdateTest(int $caseID, array $param = array()): bool|array|object
{
$oldCase = $this->objectModel->getByID($caseID);
$case = new stdclass();
$case->id = $oldCase->id;
$case->title = $oldCase->title;
$case->color = $oldCase->color;
$case->precondition = $oldCase->precondition;
$case->steps = array('用例步骤描述1');
$case->stepType = array('step');
$case->expects = array('这是用例预期结果1');
$case->comment = '';
$case->lastEditedDate = $oldCase->lastEditedDate;
$case->product = $oldCase->product;
$case->module = $oldCase->module;
$case->story = $oldCase->story;
$case->type = $oldCase->type;
$case->stage = $oldCase->stage;
$case->pri = $oldCase->pri;
$case->status = $oldCase->status;
$case->keywords = $oldCase->keywords;
$case->linkBug = array();
foreach($param as $field => $value) $case->$field = $value;
$this->objectModel->doUpdate($case);
if(dao::isError()) return dao::getError();
return $this->objectModel->fetchBaseInfo($caseID);
}
/**
* 测试导入测试用例到用例库。
* Test import cases to lib.
*
* @param array $caseIdList
* @access public
* @return string
*/
public function importToLibTest(array $caseIdList): string
{
$cases = $this->objectModel->getByList($caseIdList);
global $tester;
$files = $tester->dao->select('*')->from(TABLE_FILE)->where('`objectID`')->in($caseIdList)->andWhere('objectType')->eq('testcase')->fetchGroup('objectID', 'id');
$steps = $tester->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->in($caseIdList)->fetchGroup('case', 'id');
$importCases = array();
$libCases = $tester->dao->select('*')->from(TABLE_CASE)->where('`fromCaseID`')->in($caseIdList)->fetchGroup('fromCaseID', 'id');
foreach($cases as $caseID => $case)
{
$libCase = new stdclass();
$libCase->lib = '1';
$libCase->product = '0';
$libCase->title = $case->title;
$libCase->precondition = $case->precondition;
$libCase->keywords = $case->keywords;
$libCase->pri = $case->pri;
$libCase->type = $case->type;
$libCase->stage = $case->stage;
$libCase->status = $case->status;
$libCase->fromCaseID = $case->id;
$libCase->fromCaseVersion = $case->version;
$libCase->order = $case->order;
$libCase->module = 0;
$libCaseID = 0;
if(empty($libCases[$caseID]))
{
$libCase->openedBy = $tester->app->user->account;
$libCase->openedDate = helper::now();
}
else
{
$libCaseList = array_keys($libCases[$caseID]);
$libCaseID = $libCaseList[0];
$libCase->id = $libCaseID;
$libCase->lastEditedBy = $tester->app->user->account;
$libCase->lastEditedDate = helper::now();
$libCase->version = (int)$libCases[$case->id][$libCaseID]->version + 1;
}
if(!isset($steps[$caseID])) $steps[$caseID] = array();
foreach($steps[$caseID] as $stepID => $step)
{
$step->version = zget($libCase, 'version', '0');
unset($step->id);
}
if(!isset($files[$caseID])) $files[$caseID] = array();
foreach($files[$caseID] as $fileID => $file)
{
$file->oldpathname = $file->pathname;
$file->pathname = str_replace('.', "copy{$libCaseID}.", $file->pathname);
}
$importCases[] = $libCase;
}
$this->objectModel->importToLib($importCases, $steps, $files);
if(dao::isError()) return dao::getError()[0];
$return = '';
$libCases = $tester->dao->select('*')->from(TABLE_CASE)->where('`fromCaseID`')->in($caseIdList)->fetchGroup('fromCaseID', 'id');
foreach($libCases as $caseID => $cases)
{
foreach($cases as $libCase)
{
$steps = $tester->dao->select('id')->from(TABLE_CASESTEP)->where('`case`')->eq($libCase->id)->fetchPairs();
$files = $tester->dao->select('id')->from(TABLE_FILE)->where('`objectID`')->eq($libCase->id)->andWhere('objectType')->eq('testcase')->fetchPairs();
$return .= $caseID . ': ' . implode(',', $steps) . ' ' . implode(',', $files) . '; ';
}
}
return trim($return);
}
}
+108
View File
@@ -1417,6 +1417,7 @@ class testcaseZen extends testcase
}
/**
* 构建从用例库导入的数据。
* Build data for importing from lib.
*
* @param int $productID
@@ -1496,6 +1497,66 @@ class testcaseZen extends testcase
return array($cases, $steps, $files, $imported);
}
/**
* 构建导入到用例库的数据。
* Build data for import to lib.
*
* @param int $caseID
* @param int $libID
* @access protected
* @return array
*/
protected function buildDataForImportToLib(int $caseID, int $libID): array
{
$cases = array();
$steps = array();
$files = array();
$caseIdList = !empty($caseID) ? $caseID : $this->post->caseIdList;
$caseIdList = str_replace('case_' , '', $caseIdList);
$caseIdList = explode(',' , $caseIdList);
$fromCases = $this->testcase->getByList($caseIdList);
$fromSteps = $this->testcase->fetchStepsByList($caseIdList);
$fromFiles = $this->testcase->getRelatedFiles($caseIdList);
$libCases = $this->loadModel('caselib')->getLibCases($libID, 'all');
$libCases = $this->dao->select('*')->from(TABLE_CASE)->where('lib')->eq($libID)->andWhere('product')->eq(0)->andWhere('deleted')->eq('0')->fetchGroup('fromCaseID', 'id');
$maxOrder = $this->dao->select('max(`order`) as maxOrder')->from(TABLE_CASE)->where('deleted')->eq(0)->fetch('maxOrder');
$maxModuleOrder = $this->dao->select('max(`order`) as maxOrder')->from(TABLE_MODULE)->where('deleted')->eq(0)->fetch('maxOrder');
foreach($fromCases as $caseID => $case)
{
/* 初始化用例。 */
/* Init case. */
$libCase = $this->initLibCase($case, $libID, ++ $maxOrder, $maxModuleOrder, $libCases);
/* 设置用例步骤。 */
/* Set case steps. */
$steps[$caseID] = array();
if(!isset($fromSteps[$caseID])) $fromSteps[$caseID] = array();
foreach($fromSteps[$caseID] as $step)
{
$stepID = $step->id;
$step->version = zget($libCase, 'version', '0');
unset($step->id);
$steps[$caseID][$stepID] = $step;
}
/* 设置用例文件。 */
/* Set case files. */
$files[$caseID] = array();
if(!isset($fromFiles[$caseID])) $fromFiles[$caseID] = array();
foreach($fromFiles[$caseID] as $file)
{
$file->oldpathname = $file->pathname;
$file->pathname = str_replace('.', "copy{$libCase->id}.", $file->pathname);
$files[$caseID][$file->id] = $file;
}
$cases[$caseID] = $libCase;
}
return array($cases, $steps, $files);
}
/**
* 为展示导入用例构建更新的用例。
* Build update case for showing import.
@@ -1753,6 +1814,53 @@ class testcaseZen extends testcase
return $case;
}
/**
* 初始化要导入到用例库的用例
* Init case to import to lib.
*
* @param object $case
* @param int $libID
* @param int $maxOrder
* @param int $maxModuleOrder
* @param bool $isImported
* @access protected
* @return object
*/
protected function initLibCase(object $case, int $libID, int $maxOrder, int $maxModuleOrder, array $libCases): object
{
$libCase = new stdclass();
$libCase->lib = $libID;
$libCase->title = $case->title;
$libCase->precondition = $case->precondition;
$libCase->keywords = $case->keywords;
$libCase->pri = $case->pri;
$libCase->type = $case->type;
$libCase->stage = $case->stage;
$libCase->status = $case->status;
$libCase->fromCaseID = $case->id;
$libCase->fromCaseVersion = $case->version;
$libCase->order = $maxOrder;
$libCase->module = empty($case->module) ? 0 : $this->importCaseRelatedModules($libID, $case->module, $maxModuleOrder);
if(!isset($libCases[$case->id]))
{
$libCase->openedBy = $this->app->user->account;
$libCase->openedDate = helper::now();
}
else
{
$libCaseList = array_keys($libCases[$case->id]);
$libCaseID = $libCaseList[0];
$libCase->id = $libCaseID;
$libCase->lastEditedBy = $this->app->user->account;
$libCase->lastEditedDate = helper::now();
$libCase->version = (int)$libCases[$case->id][$libCaseID]->version + 1;
}
return $libCase;
}
/**
* 导入用例。
* Import cases.