fix(接口测试): 修复跟随API定义对array类型处理问题

--bug=1008043 --user=赵勇 【接口测试】文档结构断言-跟随API定义,少了一个字段 https://www.tapd.cn/55049933/s/1069717
This commit is contained in:
fit2-zhao 2021-11-18 13:37:23 +08:00 committed by fit2-zhao
parent 9f86e78b69
commit 6ae55cfa84
4 changed files with 82 additions and 65 deletions

View File

@ -46,6 +46,22 @@ public class DocumentElement {
} }
} }
public DocumentElement(String name, String type, Object expectedOutcome, boolean typeVerification, List<DocumentElement>children) {
this.id = UUID.randomUUID().toString();
this.name = name;
this.expectedOutcome = expectedOutcome;
this.type = type;
this.typeVerification = typeVerification;
this.children = children == null ? this.children = new LinkedList<>() : children;
this.rowspan = 1;
this.contentVerification = "value_eq";
if (StringUtils.equalsAny(type, "object", "array")) {
this.contentVerification = "none";
} else if (expectedOutcome == null || StringUtils.isEmpty(expectedOutcome.toString())) {
this.contentVerification = "none";
}
}
public DocumentElement(String id, String name, String type, Object expectedOutcome, List<DocumentElement> children) { public DocumentElement(String id, String name, String type, Object expectedOutcome, List<DocumentElement> children) {
this.id = id; this.id = id;
this.name = name; this.name = name;

View File

@ -33,6 +33,7 @@ import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*; import io.metersphere.base.mapper.ext.*;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.json.JSONSchemaToDocumentUtils;
import io.metersphere.commons.json.JSONToDocumentUtils; import io.metersphere.commons.json.JSONToDocumentUtils;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.controller.request.ResetOrderRequest; import io.metersphere.controller.request.ResetOrderRequest;
@ -1744,7 +1745,12 @@ public class ApiDefinitionService {
String dataType = body.getString("type"); String dataType = body.getString("type");
if (StringUtils.isNotEmpty(raw) && StringUtils.isNotEmpty(dataType)) { if (StringUtils.isNotEmpty(raw) && StringUtils.isNotEmpty(dataType)) {
if (StringUtils.equals(type, "JSON")) { if (StringUtils.equals(type, "JSON")) {
String format = body.getString("format");
if (StringUtils.equals(format, "JSON-SCHEMA") && StringUtils.isNotEmpty(body.getString("jsonSchema"))) {
elements = JSONSchemaToDocumentUtils.getDocument(body.getString("jsonSchema"));
}else {
elements = JSONToDocumentUtils.getDocument(raw, dataType); elements = JSONToDocumentUtils.getDocument(raw, dataType);
}
} else if (StringUtils.equals(dataType, "XML")) { } else if (StringUtils.equals(dataType, "XML")) {
elements = JSONToDocumentUtils.getDocument(raw, type); elements = JSONToDocumentUtils.getDocument(raw, type);
} }

View File

@ -2,9 +2,11 @@ package io.metersphere.commons.json;
import com.google.gson.*; import com.google.gson.*;
import io.metersphere.api.dto.definition.request.assertions.document.DocumentElement; import io.metersphere.api.dto.definition.request.assertions.document.DocumentElement;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.jmeter.utils.ScriptEngineUtils; import io.metersphere.jmeter.utils.ScriptEngineUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -18,17 +20,23 @@ public class JSONSchemaToDocumentUtils {
} }
private static void analyzeObject(JsonObject object, List<DocumentElement> roots) { private static void analyzeObject(JsonObject object, List<DocumentElement> roots) {
List<String> requiredList = new ArrayList<>();
if (object.get("required") != null) {
JsonArray jsonElements = object.get("required").getAsJsonArray();
for (JsonElement jsonElement : jsonElements) {
requiredList.add(jsonElement.getAsString());
}
}
if (object.has("allOf")) { if (object.has("allOf")) {
JsonArray allOfArray = object.get("allOf").getAsJsonArray(); JsonArray allOfArray = object.get("allOf").getAsJsonArray();
for (JsonElement allOfElement : allOfArray) { for (JsonElement allOfElement : allOfArray) {
JsonObject allOfElementObj = allOfElement.getAsJsonObject(); JsonObject allOfElementObj = allOfElement.getAsJsonObject();
if (allOfElementObj.has("properties")) { if (allOfElementObj.has("properties")) {
// Properties elements will become the attributes/references of the element
JsonObject propertiesObj = allOfElementObj.get("properties").getAsJsonObject(); JsonObject propertiesObj = allOfElementObj.get("properties").getAsJsonObject();
for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) { for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) {
String propertyKey = entry.getKey(); String propertyKey = entry.getKey();
JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject(); JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject();
analyzeProperty(roots, propertyKey, propertyObj); analyzeProperty(roots, propertyKey, propertyObj, requiredList);
} }
} }
} }
@ -37,17 +45,17 @@ public class JSONSchemaToDocumentUtils {
for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) { for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) {
String propertyKey = entry.getKey(); String propertyKey = entry.getKey();
JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject(); JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject();
analyzeProperty(roots, propertyKey, propertyObj); analyzeProperty(roots, propertyKey, propertyObj, requiredList);
} }
} else if (object.has("type") && object.get("type").getAsString().equals("array")) { } else if (object.has("type") && object.get("type").getAsString().equals("array")) {
analyzeProperty(roots, "MS-OBJECT", object); analyzeProperty(roots, "MS-OBJECT", object, requiredList);
} else if (object.has("type") && !object.get("type").getAsString().equals("object")) { } else if (object.has("type") && !object.get("type").getAsString().equals("object")) {
analyzeProperty(roots, object.getAsString(), object); analyzeProperty(roots, object.getAsString(), object, requiredList);
} }
} }
private static void analyzeProperty(List<DocumentElement> concept, private static void analyzeProperty(List<DocumentElement> concept,
String propertyName, JsonObject object) { String propertyName, JsonObject object, List<String> requiredList) {
if (object.has("type")) { if (object.has("type")) {
String propertyObjType = null; String propertyObjType = null;
if (object.get("type") instanceof JsonPrimitive) { if (object.get("type") instanceof JsonPrimitive) {
@ -56,35 +64,36 @@ public class JSONSchemaToDocumentUtils {
JsonArray typeArray = (JsonArray) object.get("type").getAsJsonArray(); JsonArray typeArray = (JsonArray) object.get("type").getAsJsonArray();
propertyObjType = typeArray.get(0).getAsString(); propertyObjType = typeArray.get(0).getAsString();
} }
Object value = null;
boolean required = requiredList.contains(propertyName);
if (object.has("default")) { if (object.has("default")) {
concept.add(new DocumentElement(propertyName, propertyObjType, object.get("default") != null ? object.get("default").toString() : "", null)); value = object.get("default") != null ? object.get("default").toString() : "";
concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (object.has("enum")) { } else if (object.has("enum")) {
try { try {
if (object.has("mock") && object.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString())) { if (object.has("mock") && object.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString())) {
Object value = object.get("mock").getAsJsonObject().get("mock"); value = object.get("mock").getAsJsonObject().get("mock");
concept.add(new DocumentElement(propertyName, propertyObjType, value.toString(), null));
} else { } else {
List<Object> list = analyzeEnumProperty(object); List<Object> list = analyzeEnumProperty(object);
if (list.size() > 0) { if (list.size() > 0) {
int index = (int) (Math.random() * list.size()); int index = (int) (Math.random() * list.size());
concept.add(new DocumentElement(propertyName, propertyObjType, list.get(index).toString(), null)); value = list.get(index).toString();
} }
} }
} catch (Exception e) { } catch (Exception e) {
concept.add(new DocumentElement(propertyName, propertyObjType, "", null)); LogUtil.error(e);
} }
concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (propertyObjType.equals("string")) { } else if (propertyObjType.equals("string")) {
// 先设置空值 // 先设置空值
String value = "";
if (object.has("default")) { if (object.has("default")) {
value = object.get("default") != null ? object.get("default").toString() : ""; value = object.get("default") != null ? object.get("default").toString() : "";
} }
if (object.has("mock") && object.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString()) && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString())) { if (object.has("mock") && object.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString()) && StringUtils.isNotEmpty(object.get("mock").getAsJsonObject().get("mock").getAsString())) {
value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString()); value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString());
} }
concept.add(new DocumentElement(propertyName, propertyObjType, value, null)); concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (propertyObjType.equals("integer")) { } else if (propertyObjType.equals("integer")) {
Object value = null;
if (object.has("default")) { if (object.has("default")) {
value = object.get("default"); value = object.get("default");
} }
@ -95,9 +104,8 @@ public class JSONSchemaToDocumentUtils {
value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString()); value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString());
} }
} }
concept.add(new DocumentElement(propertyName, propertyObjType, value, null)); concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (propertyObjType.equals("number")) { } else if (propertyObjType.equals("number")) {
Object value = null;
if (object.has("default")) { if (object.has("default")) {
value = object.get("default"); value = object.get("default");
} }
@ -108,9 +116,8 @@ public class JSONSchemaToDocumentUtils {
value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString()); value = ScriptEngineUtils.buildFunctionCallString(object.get("mock").getAsJsonObject().get("mock").getAsString());
} }
} }
concept.add(new DocumentElement(propertyName, propertyObjType, value, null)); concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (propertyObjType.equals("boolean")) { } else if (propertyObjType.equals("boolean")) {
Object value = null;
if (object.has("default")) { if (object.has("default")) {
value = object.get("default"); value = object.get("default");
} }
@ -120,9 +127,12 @@ public class JSONSchemaToDocumentUtils {
} catch (Exception e) { } catch (Exception e) {
} }
} }
concept.add(new DocumentElement(propertyName, propertyObjType, value, null)); concept.add(new DocumentElement(propertyName, propertyObjType, value, required, null));
} else if (propertyObjType.equals("array")) { } else if (propertyObjType.equals("array")) {
analyzeArray(propertyObjType, propertyName, object); List<DocumentElement> elements = new LinkedList<>();
concept.add(new DocumentElement(propertyName, propertyObjType, "", requiredList.contains(propertyName), elements));
JsonArray jsonArray = object.get("items").getAsJsonArray();
analyzeArray(propertyName, jsonArray, elements, requiredList);
} else if (propertyObjType.equals("object")) { } else if (propertyObjType.equals("object")) {
List<DocumentElement> list = new LinkedList<>(); List<DocumentElement> list = new LinkedList<>();
concept.add(new DocumentElement(propertyName, propertyObjType, "", list)); concept.add(new DocumentElement(propertyName, propertyObjType, "", list));
@ -131,51 +141,26 @@ public class JSONSchemaToDocumentUtils {
} }
} }
private static void analyzeArray(String propertyObjType, String propertyName, JsonObject object) { private static void analyzeArray(String propertyName, JsonArray jsonArray, List<DocumentElement> array, List<String> requiredList) {
// 先设置空值
List<DocumentElement> array = new LinkedList<>();
JsonArray jsonArray = new JsonArray();
if (object.has("items") && object.get("items").isJsonArray()) {
jsonArray = object.get("items").getAsJsonArray();
} else {
JsonObject itemsObject = object.get("items").getAsJsonObject();
array.add(new DocumentElement(propertyName, propertyObjType, itemsObject, null));
}
for (int i = 0; i < jsonArray.size(); i++) { for (int i = 0; i < jsonArray.size(); i++) {
JsonObject itemsObject = jsonArray.get(i).getAsJsonObject(); JsonElement obj = jsonArray.get(i);
if (object.has("items")) { if (obj.isJsonArray()) {
Object value = null; JsonArray itemsObject = obj.getAsJsonArray();
if (itemsObject.has("mock") && itemsObject.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString())) { List<DocumentElement> elements = new LinkedList<>();
try { array.add(new DocumentElement(propertyName, "", "", requiredList.contains("" + i + ""), elements));
value = itemsObject.get("mock").getAsJsonObject().get("mock").getAsInt(); analyzeArray("", itemsObject, elements, requiredList);
} catch (Exception e) { } else if (obj.isJsonObject()) {
value = ScriptEngineUtils.buildFunctionCallString(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString()); List<String> requiredItems = new ArrayList<>();
} if (obj.getAsJsonObject().get("required") != null) {
} else if (itemsObject.has("type") && itemsObject.get("type").getAsString().equals("string")) { JsonArray jsonElements = obj.getAsJsonObject().get("required").getAsJsonArray();
if (itemsObject.has("default")) { for (JsonElement jsonElement : jsonElements) {
value = itemsObject.get("default"); requiredItems.add(jsonElement.getAsString());
} else if (itemsObject.has("mock") && itemsObject.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString())) {
value = ScriptEngineUtils.buildFunctionCallString(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString());
}
} else if (itemsObject.has("type") && itemsObject.get("type").getAsString().equals("number")) {
if (itemsObject.has("default")) {
value = itemsObject.get("default");
} else if (itemsObject.has("mock") && itemsObject.get("mock").getAsJsonObject() != null && StringUtils.isNotEmpty(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString())) {
value = ScriptEngineUtils.buildFunctionCallString(itemsObject.get("mock").getAsJsonObject().get("mock").getAsString());
}
} else if (itemsObject.has("properties")) {
List<DocumentElement> propertyConcept = new LinkedList<>();
JsonObject propertiesObj = itemsObject.get("properties").getAsJsonObject();
for (Entry<String, JsonElement> entry : propertiesObj.entrySet()) {
String propertyKey = entry.getKey();
JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject();
analyzeProperty(propertyConcept, propertyKey, propertyObj);
} }
} }
array.add(new DocumentElement(propertyName, itemsObject.get("type").getAsString(), value, null)); analyzeProperty(array, "0", obj.getAsJsonObject(), requiredItems);
} else if (object.has("items") && object.get("items").isJsonArray()) { } else {
JsonArray itemsObjectArray = object.get("items").getAsJsonArray(); JsonPrimitive primitive = (JsonPrimitive) obj;
array.add(new DocumentElement(propertyName, itemsObject.get("type").getAsString(), itemsObjectArray, null)); array.add(new DocumentElement(propertyName, primitive.getAsString(), "", requiredList.contains(propertyName), null));
} }
} }
} }
@ -207,7 +192,17 @@ public class JSONSchemaToDocumentUtils {
JsonObject rootElement = element.getAsJsonObject(); JsonObject rootElement = element.getAsJsonObject();
List<DocumentElement> roots = new LinkedList<>(); List<DocumentElement> roots = new LinkedList<>();
analyzeRootSchemaElement(rootElement, roots); analyzeRootSchemaElement(rootElement, roots);
if (rootElement.get("type") != null) {
if (rootElement.get("type").toString().equals("object")) {
return new LinkedList<DocumentElement>() {{
this.add(new DocumentElement().newRoot("root", roots));
}};
} else {
return new LinkedList<DocumentElement>() {{
this.add(new DocumentElement().newRoot("array", roots));
}};
}
}
return roots; return roots;
} }
} }

View File

@ -73,7 +73,7 @@ public class JSONToDocumentUtils {
return getXmlDocument(json); return getXmlDocument(json);
} else { } else {
return new LinkedList<DocumentElement>() {{ return new LinkedList<DocumentElement>() {{
this.add(new DocumentElement().newRoot("root", null)); this.add(new DocumentElement().newRoot("object", null));
}}; }};
} }
} catch (Exception e) { } catch (Exception e) {