package direct;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.skyscreamer.jsonassert.comparator.DefaultComparator;
import org.skyscreamer.jsonassert.JSONCompare; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map; import static org.skyscreamer.jsonassert.comparator.JSONCompareUtil.*; /**
* Created by jenny zhang on 2017/9/19.
*/
public class LooseyJSONComparator extends DefaultComparator {
private int scale; //精度,scale=5,表示精确到小数点后5位
private Double accuracy; //精度,accuracy=0.00001,表示精确到小数点后5位
String extraInfo;
def log; public LooseyJSONComparator(JSONCompareMode mode, int scale,String extraInfo,def log) {
super(mode);
this.scale = scale;
this.accuracy = 1.0/Math.pow(10,scale);
this.extraInfo = extraInfo;
this.log = log;
} public static void assertEquals( String expected, String actual, int scale, String extraInfo, def log) throws JSONException {
JSONCompareResult result = JSONCompare.compareJSON(expected, actual, new LooseyJSONComparator(JSONCompareMode.NON_EXTENSIBLE,scale,extraInfo,log));
if (result.failed()) {
def failMessage = result.getMessage();
throw new AssertionError(extraInfo + failMessage);
}
else{
log.info "pass";
}
} @Override
protected void compareJSONArrayOfJsonObjects(String key, JSONArray expected, JSONArray actual, JSONCompareResult result) throws JSONException {
String uniqueKey = findUniqueKey(expected);
if (uniqueKey == null || !isUsableAsUniqueKey(uniqueKey, actual)) {
// An expensive last resort
recursivelyCompareJSONArray(key, expected, actual, result);
return;
} Map<Object, JSONObject> expectedValueMap = arrayOfJsonObjectToMap(expected, uniqueKey, log);
Map<Object, JSONObject> actualValueMap = arrayOfJsonObjectToMap(actual, uniqueKey, log); for (Object id : expectedValueMap.keySet()) {
if (!actualValueMap.containsKey(id)) {
result.missing(formatUniqueKey(key, uniqueKey, expectedValueMap.get(id).get(uniqueKey)),
expectedValueMap.get(id));
continue;
}
JSONObject expectedValue = expectedValueMap.get(id);
JSONObject actualValue = actualValueMap.get(id);
compareValues(formatUniqueKey(key, uniqueKey, id), expectedValue, actualValue, result);
}
for (Object id : actualValueMap.keySet()) {
if (!expectedValueMap.containsKey(id)) {
result.unexpected(formatUniqueKey(key, uniqueKey, actualValueMap.get(id).get(uniqueKey)), actualValueMap.get(id));
}
}
} private String getCompareValue(String value) {
try{
return new BigDecimal(value).setScale(scale, RoundingMode.HALF_EVEN).toString();
} catch (NumberFormatException e) {
return value; //value may = NaN, in this case, return value directly.
}
} private boolean isNumeric(Object value) {
try {
Double.parseDouble(value.toString());
return true;
} catch (NumberFormatException e) {
return false;
}
} public Map<Object, JSONObject> arrayOfJsonObjectToMap(JSONArray array, String uniqueKey,def log) throws JSONException {
Map<Object, JSONObject> valueMap = new HashMap<Object, JSONObject>();
for (int i = 0; i < array.length(); ++i) {
JSONObject jsonObject = (JSONObject) array.get(i);
Object id = jsonObject.get(uniqueKey);
id = isNumeric(id) ? getCompareValue(id.toString()) : id;
valueMap.put(id, jsonObject);
}
return valueMap;
} @Override
public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException {
if (areLeaf(expectedValue, actualValue)) { if (isNumeric(expectedValue) && isNumeric(actualValue)) {
//For special numeric, such as NaN, convert to string to compare
boolean equalsAsSpecialNumeric = (expectedValue.toString().equals(actualValue.toString())) //For normal numeric, such as 153.6960001, 1.56E5, subtract and then get abosolute value
boolean equalsAsGeneralNumeric = Math.abs(Double.parseDouble(expectedValue.toString())-Double.parseDouble(actualValue.toString()))<accuracy; if (equalsAsSpecialNumeric||equalsAsGeneralNumeric) {
result.passed();
} else {
result.fail(prefix, expectedValue, actualValue);
}
return;
}
}
super.compareValues(prefix, expectedValue, actualValue, result);
} private boolean areLeaf(Object expectedValue, Object actualValue) {
boolean isLeafExpectedValue = !(expectedValue instanceof JSONArray)&&!(expectedValue instanceof JSONObject);
boolean isLeafActualValue = !(actualValue instanceof JSONArray)&&!(actualValue instanceof JSONObject);
return isLeafExpectedValue&&isLeafActualValue;
}
}

  SoapUI 里面进行调用:

package direct
import org.json.* //Get test step name
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 //Get extra information, get case number in loop
String caseNum = context.expand('${DataSource#caseNumber}')
String extraInfo = caseNum+ ", " //Get more extra information, get request ID
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"
} //Get json response and compare them
try{
String expectedJsonResponse = new JSONObject(context.expand( '${'+prePreStepName+'#Response}' ))
String actualJsonResponse = new JSONObject(context.expand( '${'+previousStepName+'#Response}' ))
LooseyJSONComparator.assertEquals(expectedJsonResponse, actualJsonResponse,5,extraInfo,log)
}
catch(JSONException e){
assert false,extraInfo+"HTTP Response is not JSON"
}

  

【SoapUI】比较Json response的更多相关文章

  1. 使用Groovy处理SoapUI中Json response

    最近工作中,处理最多的就是xml和json类型response,在SoapUI中request里面直接添加assertion处理json response的话,可以采用以下方式: import gro ...

  2. [SoapUI] Compare JSON Response(比较jsonobject)

    http://jsonassert.skyscreamer.org/ 从这个网站下载jsonassert-1.5.0.jar ,也可以下载到源代码 JSONObject data = getRESTD ...

  3. [SoapUI] 比较JSON Response

    比较两个JSON, ID是数字时,处理成统一的格式:只保留小数点后5位 package direct; import org.json.JSONArray; import org.json.JSONE ...

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

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

  5. datatable fix error–Invalid JSON response

    This error is pretty common. Meaning:When loading data by Ajax(ajax|option).DataTables by default, e ...

  6. [SoapUI] 通过JSONAssert比较两个环境的JSON Response,定制化错误信息到Excel

    package ScriptLibrary; import org.json.JSONArray; import org.json.JSONException; import org.json.JSO ...

  7. SoapUI对于Json数据进行属性值获取与传递

    SoapUI的Property Transfer功能可以很好地对接口请求返回的数据进行参数属性获取与传递,但对于Json数据,SoapUI会把数据格式先转换成XML格式,但实际情况却是,转换后的XML ...

  8. How parse REST service JSON response

    1. get JSON responses and go to : http://json2csharp.com/ 2. write data contracts using C# All class ...

  9. [JSON] Validating/Asserting JSON response with Jsonlurper

    import groovy.json.JsonSlurper def response = messageExchange.response.responseContent log.info &quo ...

随机推荐

  1. APP支付-》支付宝RSA2->支付与验签

    第一次配置支付宝,按照官网示例搞了一天,走不通.经过两天的踩坑,百度了大神的代码,支付宝终于可以了. 1:下载这是官网的最新SDK 2:配置SDK,添加命名空间 AopClient.php文件: Si ...

  2. 使用Js控制ReactRouter路由

    [使用Js控制ReactRouter路由] 首先引入PropTypes: const PropTypes = require('prop-types'); 然后定义context的router属性: ...

  3. Appium 1.6安装步骤

    原来用的Appium1.5.3GUI版本,那为什么升级呢? 为了兼容最新版本的iOS10和Android7 Xcode8升级后,将不支持使用UIAutomation,而是改为使用XCUITest了,并 ...

  4. display:none和visibility:hidden

    display:none和visibility:hidden的区别在哪儿? “这个问题简单?”我心里头暗自得意,按耐住自己得意又紧张的小心脏,自信满满地说,“这两个声明都可以让元素隐藏,不同之处在于d ...

  5. pta6-17(另类堆栈)

    题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101313244872126464 题意:一种新的堆栈,用Top表 ...

  6. PAT1021(dfs 连通分量)

    A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...

  7. Python+Selenium学习--浏览器设置

    场景 设置浏览器窗口的大小有下面两个比较常见的用途: 在统一的浏览器大小下运行用例,可以比较容易的跟一些基于图像比对的工具进行结合,提升测试的灵活性及普遍适用性.比如可以跟sikuli结合,使用sik ...

  8. vue axios请求/响应拦截器

    // main.js中配置 // 引入 axios import Axios from 'axios' // 这时候如果在其它的组件中,是无法使用 axios 命令的. // 但如果将 axios 改 ...

  9. FortiGate基本信息

    1.介绍 FortiGate是全新的下一代防火墙,在整个硬件架构和系统上面都有新的设计,在性能和功能上面都有了很大提升,具有性能高.接口丰富.功能齐全.安全路由交换一体化.性价比高等优势. Forti ...

  10. day 23 网络编程

    C/S架构 Client与Server B/S架构 Browser与Server windows上查看端口占用情况 netstat -a OSI七层模型: 其他略...