重载JSONComparator比对JSON Response,忽略小数点后几位,将科学计数法转换为普通数字进行比对,在错误信息中打印当前循环的case number及其他附加信息
package direct import org.skyscreamer.jsonassert.* import org.skyscreamer.jsonassert.comparator.* import org.json.* import net.sf.json.JSONException import java.text.NumberFormat public class LooseyJSONComparator extends DefaultComparator { def extraInfo def regEx_Numeric = '-?[1-9]\d*$|-?([1-9]\d*\.\d*|0\.\d*|0?\.0+|0)$' //匹配内容为数字的字符串 def regEx_ScientificNotation = '^((-?\d+.?\d*)[Ee]{1}(-?\d+))$' //科学计数法正则表达式 int decimalPrecision = 5 //默认精度为小数点后5位 public LooseyJSONComparator(JSONCompareMode mode) { super(mode) } //支持错误日志输出附加信息,譬如循环时的case number,请求的requestID等 public LooseyJSONComparator(JSONCompareMode mode,def extraInfo) { super(mode) this.extraInfo = extraInfo } public static void assertEquals( Object expected, Object actual) throws JSONException { JSONCompareResult result = JSONCompare.compareJSON(expected, actual, new LooseyJSONComparator(JSONCompareMode.LENIENT)) if (result.failed()) { throw new AssertionError(result.getMessage()) } } public static void assertEquals( Object expected, Object actual, def extraInfo) throws JSONException { JSONCompareResult result = JSONCompare.compareJSON(expected, actual, new LooseyJSONComparator(JSONCompareMode.LENIENT)) if (result.failed()) { throw new AssertionError(extraInfo+result.getMessage()) } } @Override public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException { if (expectedValue instanceof String && actualValue instanceof String) { def expectedValueTemp=formatDecimalPrecision(expectedValue) def actualValueTemp=formatDecimalPrecision(actualValue) if (expectedValueTemp!=actualValueTemp){ result.fail(prefix, expectedValue, actualValue) } } else if (expectedValue.getClass().isAssignableFrom(actualValue.getClass())) { if (expectedValue instanceof JSONArray) { compareJSONArray(prefix, (JSONArray) expectedValue, (JSONArray) actualValue, result) } else if (expectedValue instanceof JSONObject) { compareJSON(prefix, (JSONObject) expectedValue, (JSONObject) actualValue, result) } else if (!expectedValue.equals(actualValue)) { result.fail(prefix, expectedValue, actualValue) } } else { result.fail(prefix, expectedValue, actualValue) } } //只精确比较小数点后5位 def formatDecimalPrecision(def dataValue){ NumberFormat format = NumberFormat.getNumberInstance() format.setMaximumFractionDigits(decimalPrecision) dataValue = dataValue.toString() //将科学计数法转换为普通数字之后再处理精确度 if(dataValue.matches(regEx_ScientificNotation)){ BigDecimal db = new BigDecimal(dataValue) dataValue = db.toPlainString() } //确定字符串的内容是否为数字 if(dataValue.matches(regEx_Numeric)){ dataValue = Double.parseDouble(dataValue) dataValue = format.format(dataValue) } return dataValue } }
SoapUI里面如此调用:
package direct import org.json.* String caseNum = context.expand('${DataSource#caseNumber}') String extraInfo = caseNum+ ", " def currentStepIndex = context.currentStepIndex def previousStep = testRunner.testCase.getTestStepAt(currentStepIndex-1) def prePreStep = testRunner.testCase.getTestStepAt(currentStepIndex-2) def previousStepName = previousStep.name def prePreStepName = prePreStep.name try{ def requestIdTest =previousStep.testRequest.messageExchange.requestHeaders.get("X-API-RequestId") def requestIdBmk =prePreStep.testRequest.messageExchange.requestHeaders.get("X-API-RequestId") extraInfo += "requestIdBmk = "+requestIdBmk+", requestIdTest = "+requestIdTest+", " } catch(NullPointerException e){ assert false,extraInfo+"HTTP Request is null" } try{ def expectedJsonResponse = new JSONObject(context.expand( '${'+prePreStepName+'#Response}' )) def actualJsonResponse = new JSONObject(context.expand( '${'+previousStepName+'#Response}' )) LooseyJSONComparator.assertEquals( expectedJsonResponse, actualJsonResponse,extraInfo) } catch(JSONException e){ assert false,extraInfo+"HTTP Response is not JSON" }