zoukankan      html  css  js  c++  java
  • [SoapUI] 通过JSONAssert比较两个环境的JSON Response,定制化错误信息到Excel

    package ScriptLibrary;
    
    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;
    	ArrayList<String> ignoreKeys;
    	def testRunner
    	def context
    	def extraInfoMap
    
        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 LooseyJSONComparator(JSONCompareMode mode, int scale,def log,def context,def testRunner,def extraInfoMap,ArrayList<String> ignoreKeys) {
            super(mode);
            this.scale = scale;
    		this.accuracy = 1.0/Math.pow(10,scale);
    		this.log = log;
    		this.context = context
    		this.testRunner = testRunner
    		this.extraInfoMap = extraInfoMap
    		this.ignoreKeys = ignoreKeys;
        }
    	
    	public static void assertEquals( String expected, String actual, int scale, def log,def context=null,def testRunner=null,def extraInfoMap=null,ArrayList<String> ignoreKeys=null) throws JSONException {
            JSONCompareResult result = JSONCompare.compareJSON(expected, actual, new LooseyJSONComparator(JSONCompareMode.NON_EXTENSIBLE,scale,log,testRunner,context,extraInfoMap,ignoreKeys));
            if (result.failed()) {
    			def currentStepIndex = context.currentStepIndex
    			def testSuiteName = testRunner.testCase.getTestStepAt(currentStepIndex).getParent().getParent().getName()
    		
    			def failMessage = result.getMessage();
    			
    			if(failMessage.contains("Expected:")&&failMessage.contains("got:")&&(testRunner!=null)&&(context!=null)&&(extraInfoMap!=null)){
    				//移除老板不想看的信息
    				def keysToRemoveForBoss = ["RequestIdBmk", "RequestIdTest"]
    				def extraInfoMapForBoss = extraInfoMap.findAll({!keysToRemoveForBoss.contains(it.key)})
    			
    				def topRow=["Test Suite","Test Case"]
    				topRow = topRow+extraInfoMapForBoss.keySet()
    				topRow = topRow+["DataPoint","Bmk Env","Test Env","DetailedJsonPath"]
    				
    				//获取当前自动化测试Project所在的路径
    				String projectPath = context.expand( '${projectDir}' )
    				WriteExcel writeExcel = new WriteExcel(testRunner,context,log)
    				
    				//处理fail message,解析出来写入excel
    				ArrayList failMessageList = new ArrayList()
    				failMessageList = writeExcel.parseFailMessage(failMessage,extraInfoMapForBoss)
    				
    				//定义Excel的路径和名字
    				String filePath = projectPath+ "/TestResult/" + testSuiteName + "_Fail.xlsx"
    				File testResultFile = new File(filePath)
    				
    				//如果Excel不存在,就先创建带列名的Excel
    				if(!testResultFile.exists()){
    					writeExcel.createExcel(testResultFile,topRow)
    				}
    				//追加信息到Excel
    				writeExcel.addExcel(filePath,failMessageList)
    			}
    			//打印QA和Developer想要的错误信息到SoapUI报告
    			def extraInfoForQAAndDev = extraInfoMap.collect { k,v -> "$k=$v" }.join(',')
                throw new AssertionError(extraInfoForQAAndDev+failMessage);
            }
    		else{
    			log.info "pass";
    		}
        }
    	
    	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));
                }
            }
        }
    	
    	@Override
    	protected void checkJsonObjectKeysActualInExpected(String prefix, JSONObject expected, JSONObject actual, JSONCompareResult result) {
    		Set<String> actualKeys = getKeys(actual);
    		for (String key : actualKeys) {
    			if ((!expected.has(key))&&(!ignoreKeys.find{it == key})) {
    				result.unexpected(prefix, key);
    			}
    		}
    	}
    
        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;
        }
    }
    

      

  • 相关阅读:
    Flex布局
    【北京法院网上立案工作办法】
    欢迎注册北京法院电子诉讼平台账号
    授权书范本
    拷贝构造函数与移动构造函数
    力扣刷题计划-字符串-最长公共前缀
    多节点树结构
    WPF的TreeView添加鼠标双击事件MouseDoubleClick执行两次
    力扣刷题计划-动态规划-整数拆分
    Java解决字节流乱码问题
  • 原文地址:https://www.cnblogs.com/MasterMonkInTemple/p/9804593.html
Copyright © 2011-2022 走看看