Merge branch 'master' of https://github.com/metersphere/server
This commit is contained in:
commit
1b36e3302a
|
@ -6,7 +6,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TestCaseConstants {
|
public class TestCaseConstants {
|
||||||
|
|
||||||
public static final int MAX_NODE_DEPTH = 5;
|
public static final int MAX_NODE_DEPTH = 8;
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
Functional("functional"), Performance("performance"), Aapi("api");
|
Functional("functional"), Performance("performance"), Aapi("api");
|
||||||
|
|
|
@ -334,7 +334,12 @@ public class TestCaseService {
|
||||||
byte[] buff = new byte[1024];
|
byte[] buff = new byte[1024];
|
||||||
// 读取filename
|
// 读取filename
|
||||||
String filePath = ClassLoader.getSystemResource("template/testcase.xmind").getPath();
|
String filePath = ClassLoader.getSystemResource("template/testcase.xmind").getPath();
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)));) {
|
LogUtil.info("模版文件路径:"+filePath);
|
||||||
|
File file = new File(filePath);
|
||||||
|
if(file == null || !file.exists()){
|
||||||
|
LogUtil.info("模版模版下载失败:"+filePath);
|
||||||
|
}
|
||||||
|
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
|
||||||
int i = bis.read(buff);
|
int i = bis.read(buff);
|
||||||
while (i != -1) {
|
while (i != -1) {
|
||||||
outputStream.write(buff, 0, buff.length);
|
outputStream.write(buff, 0, buff.length);
|
||||||
|
@ -348,7 +353,7 @@ public class TestCaseService {
|
||||||
|
|
||||||
public void testCaseXmindTemplateExport(HttpServletResponse response) {
|
public void testCaseXmindTemplateExport(HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
response.setContentType("application/vnd.ms-excel");
|
response.setContentType("application/octet-stream");
|
||||||
response.setCharacterEncoding("utf-8");
|
response.setCharacterEncoding("utf-8");
|
||||||
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("思维导图用例模版", "UTF-8") + ".xmind");
|
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("思维导图用例模版", "UTF-8") + ".xmind");
|
||||||
download(response);
|
download(response);
|
||||||
|
|
|
@ -21,6 +21,8 @@ import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据转换
|
* 数据转换
|
||||||
|
@ -51,18 +53,40 @@ public class XmindToTestCaseParser {
|
||||||
protected List<TestCaseExcelData> xmindDataList;
|
protected List<TestCaseExcelData> xmindDataList;
|
||||||
|
|
||||||
// 递归处理案例数据
|
// 递归处理案例数据
|
||||||
private void makeXmind(StringBuffer processBuffer, String nodeId, int level, String nodePath, List<Attached> attacheds) {
|
private void makeXmind(StringBuffer processBuffer, Attached parent, int level, String nodePath, List<Attached> attacheds) {
|
||||||
for (Attached item : attacheds) {
|
for (Attached item : attacheds) {
|
||||||
if (!StringUtils.isEmpty(item.getTitle()) && item.getTitle().startsWith("tc")) { // 用例
|
if (isBlack(item.getTitle(), "(?:tc|tc)")) { // 用例
|
||||||
this.newTestCase(item.getTitle(), nodePath, item.getChildren() != null ? item.getChildren().getAttached() : null);
|
item.setParent(parent);
|
||||||
|
this.newTestCase(item.getTitle(), parent.getPath(), item.getChildren() != null ? item.getChildren().getAttached() : null);
|
||||||
} else {
|
} else {
|
||||||
nodePath = nodePath + "/" + item.getTitle();
|
nodePath = parent.getPath() + "/" + item.getTitle();
|
||||||
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty())
|
item.setPath(nodePath);
|
||||||
makeXmind(processBuffer, nodeId, level + 1, nodePath, item.getChildren().getAttached());
|
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
||||||
|
item.setParent(parent);
|
||||||
|
makeXmind(processBuffer, item, level + 1, nodePath, item.getChildren().getAttached());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isBlack(String str, String regex) {
|
||||||
|
// regex = "(?:tc:|tc:)"
|
||||||
|
if (StringUtils.isEmpty(str) || StringUtils.isEmpty(regex))
|
||||||
|
return false;
|
||||||
|
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||||
|
Matcher result = pattern.matcher(str);
|
||||||
|
return result.find();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replace(String str, String regex) {
|
||||||
|
if (StringUtils.isEmpty(str) || StringUtils.isEmpty(regex))
|
||||||
|
return str;
|
||||||
|
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||||
|
Matcher result = pattern.matcher(str);
|
||||||
|
str = result.replaceAll("");
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
// 获取步骤数据
|
// 获取步骤数据
|
||||||
public String getSteps(List<Attached> attacheds) {
|
public String getSteps(List<Attached> attacheds) {
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
@ -95,7 +119,7 @@ public class XmindToTestCaseParser {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 用例名称
|
// 用例名称
|
||||||
testCase.setName(tcArr[1].replace("tc:|tc:", ""));
|
testCase.setName(this.replace(tcArr[1], "tc:|tc:|tc"));
|
||||||
|
|
||||||
if (!nodePath.startsWith("/")) {
|
if (!nodePath.startsWith("/")) {
|
||||||
nodePath = "/" + nodePath;
|
nodePath = "/" + nodePath;
|
||||||
|
@ -110,7 +134,7 @@ public class XmindToTestCaseParser {
|
||||||
String otArr[] = tcArr[0].split("-");
|
String otArr[] = tcArr[0].split("-");
|
||||||
for (int i = 0; i < otArr.length; i++) {
|
for (int i = 0; i < otArr.length; i++) {
|
||||||
if (otArr[i].startsWith("P") || otArr[i].startsWith("p")) {
|
if (otArr[i].startsWith("P") || otArr[i].startsWith("p")) {
|
||||||
testCase.setPriority(otArr[i]);
|
testCase.setPriority(otArr[i].toUpperCase());
|
||||||
} else if (otArr[i].endsWith("功能测试")) {
|
} else if (otArr[i].endsWith("功能测试")) {
|
||||||
testCase.setType("functional");
|
testCase.setType("functional");
|
||||||
} else if (otArr[i].endsWith("性能测试")) {
|
} else if (otArr[i].endsWith("性能测试")) {
|
||||||
|
@ -121,20 +145,29 @@ public class XmindToTestCaseParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 测试步骤处理
|
// 测试步骤处理
|
||||||
|
List<Attached> steps = new LinkedList<>();
|
||||||
if (attacheds != null && !attacheds.isEmpty()) {
|
if (attacheds != null && !attacheds.isEmpty()) {
|
||||||
List<Attached> steps = new LinkedList<>();
|
|
||||||
attacheds.forEach(item -> {
|
attacheds.forEach(item -> {
|
||||||
if (item.getTitle().startsWith("pc")) {
|
if (isBlack(item.getTitle(), "(?:pc:|pc:)")) {
|
||||||
testCase.setPrerequisite(item.getTitle().replaceAll("(?:pc:|pc:)", ""));
|
testCase.setPrerequisite(replace(item.getTitle(), "(?:pc:|pc:)"));
|
||||||
} else if (item.getTitle().startsWith("rc")) {
|
} else if (isBlack(item.getTitle(), "(?:rc:|rc:)")) {
|
||||||
testCase.setRemark(item.getTitle().replaceAll("(?:rc:|rc:)", ""));
|
testCase.setRemark(replace(item.getTitle(), "(?:rc:|rc:)"));
|
||||||
} else {
|
} else {
|
||||||
steps.add(item);
|
steps.add(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!steps.isEmpty()) {
|
}
|
||||||
testCase.setSteps(this.getSteps(steps));
|
if (!steps.isEmpty()) {
|
||||||
}
|
testCase.setSteps(this.getSteps(steps));
|
||||||
|
} else {
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
// 保持插入顺序,判断用例是否有相同的steps
|
||||||
|
JSONObject step = new JSONObject(true);
|
||||||
|
step.put("num", 1);
|
||||||
|
step.put("desc", "");
|
||||||
|
step.put("result", "");
|
||||||
|
jsonArray.add(step);
|
||||||
|
testCase.setSteps(jsonArray.toJSONString());
|
||||||
}
|
}
|
||||||
TestCaseExcelData compartData = new TestCaseExcelData();
|
TestCaseExcelData compartData = new TestCaseExcelData();
|
||||||
BeanUtils.copyBean(compartData, testCase);
|
BeanUtils.copyBean(compartData, testCase);
|
||||||
|
@ -232,25 +265,27 @@ public class XmindToTestCaseParser {
|
||||||
|
|
||||||
// 获取思维导图内容
|
// 获取思维导图内容
|
||||||
String content = XmindParser.parseJson(file);
|
String content = XmindParser.parseJson(file);
|
||||||
if (StringUtils.isEmpty(content) || content.split("(?:tc:|tc:)").length == 1) {
|
if (StringUtils.isEmpty(content) || content.split("(?:tc:|tc:|TC:|TC:|tc|TC)").length == 1) {
|
||||||
return Translator.get("import_xmind_not_found");
|
return Translator.get("import_xmind_not_found");
|
||||||
}
|
}
|
||||||
if (!StringUtils.isEmpty(content) && content.split("(?:tc:|tc:)").length > 500) {
|
if (!StringUtils.isEmpty(content) && content.split("(?:tc:|tc:|TC:|TC:|tc|TC)").length > 500) {
|
||||||
return Translator.get("import_xmind_count_error");
|
return Translator.get("import_xmind_count_error");
|
||||||
}
|
}
|
||||||
JsonRootBean root = JSON.parseObject(content, JsonRootBean.class);
|
JsonRootBean root = JSON.parseObject(content, JsonRootBean.class);
|
||||||
|
|
||||||
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
|
if (root != null && root.getRootTopic() != null && root.getRootTopic().getChildren() != null) {
|
||||||
// 判断是模块还是用例
|
// 判断是模块还是用例
|
||||||
root.getRootTopic().getChildren().getAttached().forEach(item -> {
|
for (Attached item : root.getRootTopic().getChildren().getAttached()) {
|
||||||
if (!StringUtils.isEmpty(item.getTitle()) && item.getTitle().startsWith("tc")) { // 用例
|
if (isBlack(item.getTitle(), "(?:tc:|tc:|tc)")) { // 用例
|
||||||
this.newTestCase(item.getTitle(), "", item.getChildren() != null ? item.getChildren().getAttached() : null);
|
return replace(item.getTitle(), "(?:tc:|tc:|tc)") + ":" + Translator.get("test_case_create_module_fail");
|
||||||
} else {
|
} else {
|
||||||
item.setPath(item.getTitle());
|
item.setPath(item.getTitle());
|
||||||
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty())
|
if (item.getChildren() != null && !item.getChildren().getAttached().isEmpty()) {
|
||||||
makeXmind(processBuffer, null, 1, item.getPath(), item.getChildren().getAttached());
|
item.setPath(item.getTitle());
|
||||||
|
makeXmind(processBuffer, item, 1, item.getPath(), item.getChildren().getAttached());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(process.toString()) && !testCaseWithBLOBs.isEmpty()) {
|
if (StringUtils.isEmpty(process.toString()) && !testCaseWithBLOBs.isEmpty()) {
|
||||||
testCaseService.saveImportData(testCaseWithBLOBs, projectId);
|
testCaseService.saveImportData(testCaseWithBLOBs, projectId);
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class Attached {
|
||||||
private String title;
|
private String title;
|
||||||
private Notes notes;
|
private Notes notes;
|
||||||
private String path;
|
private String path;
|
||||||
|
private Attached parent;
|
||||||
private List<Comments> comments;
|
private List<Comments> comments;
|
||||||
private Children children;
|
private Children children;
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 89 KiB |
|
@ -54,8 +54,8 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row class="import-row">
|
<el-row class="import-row">
|
||||||
<el-card :body-style="{ padding: '0px' }">
|
<el-card :body-style="{ padding: '0px' }">
|
||||||
<img src="../../../../../assets/xmind.jpg" width="700px" height="250px"
|
<img src="../../../../../assets/xmind.jpg"
|
||||||
class="image">
|
class="testcase-import-img">
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -247,7 +247,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.testcase-import >>> .el-dialog {
|
.testcase-import >>> .el-dialog {
|
||||||
width: 700px;
|
width: 650px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testcase-import-img {
|
||||||
|
width: 614px;
|
||||||
|
height: 312px;
|
||||||
|
size: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue