重载JSONComparator比对JSON Response,忽略小数点后几位,将科学计数法转换为普通数字进行比对
封装的脚本:
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 log
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 //Defaultly compare 5 decimal places
public LooseyJSONComparator(JSONCompareMode mode) {
super(mode)
}
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())
}
}
@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)
}
}
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.*
def currentStepIndex = context.currentStepIndex
def previousStepName = testRunner.testCase.getTestStepAt(currentStepIndex-1).name
def prePreStepName = testRunner.testCase.getTestStepAt(currentStepIndex-2).name
def expectedJsonResponse =new JSONObject("{"long-rescale":"1.519719","short":"0.105816","net":"1.477390","long":"1.583196"}")
def actualJsonResponse = new JSONObject("{"long-rescale":"1.519715","short":"0.105806","net":"1.477390","long":"1.583196"}")
LooseyJSONComparator.assertEquals( expectedJsonResponse, actualJsonResponse)
输出结果:

如果是通过获取test step的response来比对,脚本如下:
package direct
import org.json.*
def currentStepIndex = context.currentStepIndex
def previousStepName = testRunner.testCase.getTestStepAt(currentStepIndex-1).name
def prePreStepName = testRunner.testCase.getTestStepAt(currentStepIndex-2).name
try{
def expectedJsonResponse = new JSONObject(context.expand( '${'+prePreStepName+'#Response}' ))
def actualJsonResponse = new JSONObject(context.expand( '${'+previousStepName+'#Response}' ))
LooseyJSONComparator.assertEquals( expectedJsonResponse, actualJsonResponse)
}catch(JSONException e){
assert false,"HTTP Response returns wrong, please have a check"
}