feat(测试用例): 测试用例的Excel模版用例状态字段增加备注、国际化的部分问题

--bug=1005222 --user=宋天阳 【测试用例】excel模版建议添加“用例状态”备注
https://www.tapd.cn/55049933/s/1028465;--bug=1005343 --user=宋天阳
【接口测试】国际化问题 https://www.tapd.cn/55049933/s/1028552
This commit is contained in:
song-tianyang 2021-07-23 16:07:05 +08:00 committed by 刘瑞斌
parent 1959fe34f8
commit 12d6b7115b
19 changed files with 138 additions and 43 deletions

View File

@ -975,11 +975,11 @@ public class ApiDefinitionService {
res.setCasePassingRate(compRes.getPassRate());
// 状态优先级 未执行未通过通过
if ((compRes.getError() + compRes.getSuccess()) < compRes.getCaseTotal()) {
res.setCaseStatus("未执行");
res.setCaseStatus(Translator.get("not_execute"));
} else if (compRes.getError() > 0) {
res.setCaseStatus("未通过");
res.setCaseStatus(Translator.get("execute_not_pass"));
} else {
res.setCaseStatus("通过");
res.setCaseStatus(Translator.get("execute_pass"));
}
} else {
res.setCaseTotal("-");

View File

@ -3,7 +3,9 @@ package io.metersphere.excel.handler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import com.alibaba.fastjson.JSONArray;
import io.metersphere.i18n.Translator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.Drawing;
@ -11,10 +13,8 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author song.tianyang
@ -26,9 +26,11 @@ public class FunctionCaseTemplateWriteHandler extends AbstractRowHeightStyleStra
private boolean isNeedId;
List<List<String>> headList = new ArrayList<>();
Map<String,Integer> rowDispseIndexMap;
public FunctionCaseTemplateWriteHandler(boolean isNeedId,List<List<String>> headList){
Map<String,List<String>> caseLevelAndStatusValueMap;
public FunctionCaseTemplateWriteHandler(boolean isNeedId,List<List<String>> headList,Map<String,List<String>> caseLevelAndStatusValueMap){
this.isNeedId = isNeedId;
rowDispseIndexMap = this.buildFiledMap(headList);
this.caseLevelAndStatusValueMap = caseLevelAndStatusValueMap;
}
private Map<String, Integer> buildFiledMap(List<List<String>> headList) {
@ -47,6 +49,8 @@ public class FunctionCaseTemplateWriteHandler extends AbstractRowHeightStyleStra
returnMap.put("Priority",index);
}else if(StringUtils.equalsAnyIgnoreCase(head,"标签","標簽","Tag")){
returnMap.put("Tag",index);
}else if(StringUtils.equalsAnyIgnoreCase(head,"用例状态","用例狀態","Case status")){
returnMap.put("Status",index);
}
index ++;
}
@ -94,12 +98,30 @@ public class FunctionCaseTemplateWriteHandler extends AbstractRowHeightStyleStra
sheet.getRow(0).getCell(1).setCellComment(comment);
}else if(StringUtils.equalsAnyIgnoreCase(coloum,"Priority")){
Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, index, 0, (short) 3, 1));
comment.setString(new XSSFRichTextString(Translator.get("options") + "P0、P1、P2、P3"));
List<String> list = new ArrayList<>();
if(caseLevelAndStatusValueMap != null && caseLevelAndStatusValueMap.containsKey("caseLevel")){
list = caseLevelAndStatusValueMap.get("caseLevel");
}
if(CollectionUtils.isEmpty(list)){
comment.setString(new XSSFRichTextString(Translator.get("options") + "P0、P1、P2、P3"));
}else {
comment.setString(new XSSFRichTextString(Translator.get("options") + JSONArray.toJSONString(list)));
}
sheet.getRow(0).getCell(1).setCellComment(comment);
}else if(StringUtils.equalsAnyIgnoreCase(coloum,"Tag")){
Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, index, 0, (short) 3, 1));
comment.setString(new XSSFRichTextString(Translator.get("tag_tip_pattern")));
sheet.getRow(0).getCell(1).setCellComment(comment);
}else if(StringUtils.equalsAnyIgnoreCase(coloum,"Status")){
List<String> list = new ArrayList<>();
if(caseLevelAndStatusValueMap != null && caseLevelAndStatusValueMap.containsKey("caseStatus")){
list = caseLevelAndStatusValueMap.get("caseStatus");
}
if(!CollectionUtils.isEmpty(list)){
Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, index, 0, (short) 3, 1));
comment.setString(new XSSFRichTextString(Translator.get("options") + JSONArray.toJSONString(list)));
sheet.getRow(0).getCell(1).setCellComment(comment);
}
}
}
}

View File

@ -46,15 +46,15 @@ public class EasyExcelExporter {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
List<List<String>> list = new ArrayList<>();
List<String>aaaList = new ArrayList<>();
aaaList.add("aaaaa");
List<String>nameList = new ArrayList<>();
nameList.add("所属模块");
List<String>name2List = new ArrayList<>();
name2List.add("用例名称");
list.add(aaaList);
list.add(nameList);
list.add(name2List);
// List<String>aaaList = new ArrayList<>();
// aaaList.add("aaaaa");
// List<String>nameList = new ArrayList<>();
// nameList.add("所属模块");
// List<String>name2List = new ArrayList<>();
// name2List.add("用例名称");
// list.add(aaaList);
// list.add(nameList);
// list.add(name2List);
try {
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
if(CollectionUtils.isNotEmpty(excludeColumnFiledNames)){

View File

@ -1,6 +1,8 @@
package io.metersphere.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.TestCaseTemplateMapper;
import io.metersphere.base.mapper.ext.ExtTestCaseTemplateMapper;
@ -24,8 +26,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.*;
@Service
@Transactional(rollbackFor = Exception.class)
@ -182,6 +183,51 @@ public class TestCaseTemplateService extends TemplateBaseService {
return testCaseTemplates;
}
public Map<String,List<String>> getCaseLevelAndStatusMapByProjectId(String projectId){
Project project = projectService.getProjectById(projectId);
String caseTemplateId = project.getCaseTemplateId();
TestCaseTemplateWithBLOBs caseTemplate = null;
TestCaseTemplateDao caseTemplateDao = new TestCaseTemplateDao();
if (StringUtils.isNotBlank(caseTemplateId)) {
caseTemplate = testCaseTemplateMapper.selectByPrimaryKey(caseTemplateId);
if (caseTemplate == null) {
caseTemplate = getDefaultTemplate(project.getWorkspaceId());
}
} else {
caseTemplate = getDefaultTemplate(project.getWorkspaceId());
}
BeanUtils.copyBean(caseTemplateDao, caseTemplate);
List<CustomFieldDao> result = customFieldService.getCustomFieldByTemplateId(caseTemplate.getId());
Map<String, List<String>> returnMap = new HashMap<>();
for (CustomFieldDao field:result) {
if(StringUtils.equalsAnyIgnoreCase(field.getScene(),"TEST_CASE")){
if(StringUtils.equalsAnyIgnoreCase(field.getName(),"用例等级")){
try {
JSONArray jsonArray = JSONArray.parseArray(field.getOptions());
List<String> values = new ArrayList<>();
for (int i = 0;i < jsonArray.size();i++) {
JSONObject obj = jsonArray.getJSONObject(i);
values.add(obj.getString("value"));
}
returnMap.put("caseLevel",values);
}catch (Exception e){}
}else if(StringUtils.equalsAnyIgnoreCase(field.getName(),"用例状态")){
try {
JSONArray jsonArray = JSONArray.parseArray(field.getOptions());
List<String> values = new ArrayList<>();
for (int i = 0;i < jsonArray.size();i++) {
JSONObject obj = jsonArray.getJSONObject(i);
values.add(obj.getString("value"));
}
returnMap.put("caseStatus",values);
}catch (Exception e){}
}
}
}
return returnMap;
}
public TestCaseTemplateDao getTemplate(String projectId) {
Project project = projectService.getProjectById(projectId);
String caseTemplateId = project.getCaseTemplateId();

View File

@ -29,10 +29,7 @@ import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.track.TestCaseReference;
import io.metersphere.service.FileService;
import io.metersphere.service.ProjectService;
import io.metersphere.service.TestCaseTemplateService;
import io.metersphere.service.UserService;
import io.metersphere.service.*;
import io.metersphere.track.dto.TestCaseCommentDTO;
import io.metersphere.track.dto.TestCaseDTO;
import io.metersphere.track.request.testcase.EditTestCaseRequest;
@ -120,6 +117,8 @@ public class TestCaseService {
private TestCaseIssuesMapper testCaseIssuesMapper;
@Resource
private IssuesMapper issuesMapper;
@Resource
private CustomFieldService customFieldService;
private void setNode(TestCaseWithBLOBs testCase) {
if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) {
@ -731,8 +730,9 @@ public class TestCaseService {
List<List<String>> headList = testCaseExcelData.getHead(importFileNeedNum, customFields);
EasyExcelExporter easyExcelExporter = new EasyExcelExporter(testCaseExcelData.getClass());
FunctionCaseTemplateWriteHandler handler = new FunctionCaseTemplateWriteHandler(importFileNeedNum, headList);
easyExcelExporter.exportByCustomWriteHandler(response, headList, generateExportDatas(importFileNeedNum),
Map<String,List<String>> caseLevelAndStatusValueMap = testCaseTemplateService.getCaseLevelAndStatusMapByProjectId(projectId);
FunctionCaseTemplateWriteHandler handler = new FunctionCaseTemplateWriteHandler(importFileNeedNum,headList,caseLevelAndStatusValueMap);
easyExcelExporter.exportByCustomWriteHandler(response,headList, generateExportDatas(importFileNeedNum),
Translator.get("test_case_import_template_name"), Translator.get("test_case_import_template_sheet"), handler);
} catch (Exception e) {
@ -968,7 +968,6 @@ public class TestCaseService {
/**
* 更新自定义字段
*
* @param request
*/
public void editTestCaseBath(TestCaseBatchRequest request) {
@ -1283,7 +1282,6 @@ public class TestCaseService {
if (editCustomFieldsPriority(dbCase, item.getPriority())) {
item.setCustomFields(dbCase.getCustomFields());
}
;
editTestCase(item);
}
});

View File

@ -217,6 +217,9 @@ message_task_already_exists=Task recipient already exists
automation_name_already_exists=the scenario already exists in the project
automation_exec_info=There are no test steps to execute
delete_check_reference_by=be referenced by Scenario
not_execute=Not execute
execute_not_pass=Not pass
execute_pass=Pass
#authsource
authsource_name_already_exists=Authentication source name already exists
authsource_name_is_null=Authentication source name cannot be empty

View File

@ -217,6 +217,9 @@ message_task_already_exists=任务接收人已经存在
automation_name_already_exists=同一个项目下,场景名称不能重复
automation_exec_info=没有测试步骤,无法执行
delete_check_reference_by=被场景引用
not_execute=未执行
execute_not_pass=未通过
execute_pass=通过
#authsource
authsource_name_already_exists=认证源名称已经存在
authsource_name_is_null=认证源名称不能为空

View File

@ -218,6 +218,9 @@ message_task_already_exists=任務接收人已經存在
automation_name_already_exists=同一個項目下,場景名稱不能重複
automation_exec_info=沒有測試步驟,無法執行
delete_check_reference_by=被場景引用
not_execute=未執行
execute_not_pass=未通過
execute_pass=通過
#authsource
authsource_name_already_exists=認證源名稱已經存在
authsource_name_is_null=認證源名稱不能為空

View File

@ -179,7 +179,7 @@ export default {
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({

View File

@ -135,7 +135,10 @@
data() {
return {
currentItem: null,
requireds: REQUIRED,
requireds: [
{name: this.$t('commons.selector.required'), id: true},
{name: this.$t('commons.selector.not_required'), id: false}
],
isSelectAll: true,
isActive: true
}

View File

@ -20,7 +20,7 @@
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"}));

View File

@ -179,7 +179,7 @@
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"}));

View File

@ -126,7 +126,7 @@
<script>
import {_getBodyUploadFiles, getCurrentProjectID, getUUID} from "@/common/js/utils";
import {PRIORITY, RESULT_MAP} from "../../model/JsonData";
import {PRIORITY} from "../../model/JsonData";
import MsTag from "../../../../common/components/MsTag";
import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
@ -173,6 +173,11 @@
return {
result: {},
grades: [],
resultMap:new Map([
['success', this.$t('test_track.plan_view.execute_result')+''+this.$t('test_track.plan_view.pass')],
['error', this.$t('test_track.plan_view.execute_result')+''+this.$t('api_test.home_page.detail_card.execution_failed')],
['default', this.$t('test_track.plan_view.execute_result')+''+this.$t('api_test.home_page.detail_card.unexecute')]
]),
showXpackCompnent: false,
isReadOnly: false,
selectedEvent: Object,
@ -390,10 +395,10 @@
item.active = !item.active;
},
getResult(data) {
if (RESULT_MAP.get(data)) {
return RESULT_MAP.get(data);
if (this.resultMap.get(data)) {
return this.resultMap.get(data);
} else {
return RESULT_MAP.get("default");
return this.resultMap.get("default");
}
},
validate(row) {

View File

@ -64,7 +64,7 @@
<ms-api-auth-config :is-read-only="isReadOnly" :request="request"/>
</el-tab-pane>
<el-tab-pane label="其他设置" name="advancedConfig">
<el-tab-pane :label="$t('api_test.definition.request.other_config')" name="advancedConfig">
<ms-api-advanced-config :is-read-only="isReadOnly" :request="request"/>
</el-tab-pane>
@ -219,7 +219,7 @@
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"}));

View File

@ -198,7 +198,7 @@
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({name: line[0], required: required, value: line[2], description: line[3], type: "text", valid: false, file: false, encode: true, enable: true, contentType: "text/plain"}));

View File

@ -101,7 +101,7 @@ export default {
params.forEach(item => {
let line = item.split(/|,/);
let required = false;
if (line[1] === '必填' || line[1] === 'true') {
if (line[1] === '必填' || line[1] === 'Required' || line[1] === 'true') {
required = true;
}
keyValues.push(new KeyValue({

View File

@ -171,6 +171,10 @@ export default {
table: {
select_tip: "Item {0} data is selected"
},
selector: {
required: "Required",
not_required: "Not required",
},
ssl: {
config: "Config",
files: "Files",
@ -750,7 +754,7 @@ export default {
definition: {
api_title: "Api test",
case_title: "Test Case",
doc_title: "Document",
doc_title: "DOC",
api_name: "Api name",
api_status: "Api status",
api_type: "Api type",
@ -758,8 +762,8 @@ export default {
api_path: "Api path",
api_principal: "Api principal",
api_last_time: "Last update time",
api_case_number: "Number use case",
api_case_status: "Ise case status",
api_case_number: "Cases",
api_case_status: "Case status",
api_case_passing_rate: "Use case pass rate",
create_tip: "Note: Detailed interface information can be filled out on the edit page",
api_import: "Api Import",

View File

@ -172,6 +172,10 @@ export default {
table: {
select_tip: "已选中 {0} 条数据"
},
selector: {
required: "必填",
not_required: "非必填",
},
ssl: {
config: "证书配置",
files: "证书文件",

View File

@ -169,6 +169,10 @@ export default {
create_user: "創建人",
run_message: "任務執行中,請到任務中心查看詳情",
executor: "執行人",
selector: {
required: "必填",
not_required: "非必填",
},
table: {
select_tip: "已選中 {0} 條數據"
},