[SoapUI] 重载JSONComparator比对JSON Response,忽略小数点后几位,将科学计数法转换为普通数字进行比对,在错误信息中打印当前循环的case number及其他附加信息

时间:2024-07-16 15:34:26

重载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"
}