基於Java+HttpClient+TestNG的接口自動化測試框架(四)-------參數存取處理


  在真正開始接口測試之前,我們需要對參數的處理進行梳理。這里所說的“參數”,既包含之前在xml中的配置(我們稱之為全局參數),也包含在每一條用例中書寫的param。全局參數為固定不變的,而根據接口相應獲取的數據是動態變化的。
  之前我們已經用${param_name}的形式,定義了如何從公共參數池中調用所需要的參數。
       並且當一個接口的請求發送完成,進行下一個接口操作的時候,我們也需要對相應的數據進行處理。例如,前面一個接口的響應中出現了下一個接口需要使用的數據,比如id,password,token等等。那么需要對這些數值進行操作(保存·),把獲取到的數據存入這個公共參數池中,然后在后續的接口請求中調用這些數據。
  對於作為測試用例數據的格式,我們可以把它設計成這樣的。

 

       在這里,我們可以看到,在url,header,param中,我們使用了${param_name}的形式,這些變量可以從我們的公共參數池中取得,而后面的verify,可以對返回值使用JSONPath來精准判定。而對於,save中的內容,我們可以將其存入公共參數池,供后面的接口進行調用。

  接下來,我們逐步來作成TestBase的基礎類,在這個類中,我們來逐步定義如何處理參數以及如何來使用參數。在這個類中,牽涉到很多關聯調用的其他工具類,在本篇中暫時不做說明。在之后的章節中來逐步去說明調用關系。
   PS:在我們寫一個程序時,如果一時不能把程序的構造想清楚,可以先用自然語言把整體邏輯描述清楚,具體的代碼可以之后再進行斟酌。
  首先,我們先需要定義一個公共參數池,以及對應與${param_name}的正則表達式。
 
    /**
     * 公共參數數據池(全局可用)
     */
    private static Map<String, String> saveDatas = new HashMap<String, String>();

    /**
     * 替換符,如果數據中包含“${}”則會被替換成公共參數中存儲的數據
     */
    protected Pattern replaceParamPattern = Pattern.compile("\\$\\{(.*?)\\}");

    /**
     * 獲取公共數據池中的數據
     * 
     * @param key
     *            公共數據的key
     * @return 對應的value
     */
    protected String getSaveData(String key) {
        if ("".equals(key) || !saveDatas.containsKey(key)) {
            return null;
        } else {
            return saveDatas.get(key);
        }
    }
    protected void setSaveDatas(Map<String, String> map) {
        saveDatas.putAll(map);
    }

  在使用過程中,我們可以將參數分為兩類。第一類為全局參數,意思是可以將之前從xml中讀取的配置,作為全局參數存入公共參數數據池,在整個接口測試運行的過程中均可進行調用。第二類是,接口過程中產生對的過程參數,即,接口A返回的數據,可以作為參數使用在接口B的請求中。這類參數在接口請求執行過程中進行定義,也存入公共參數池。

  這兩類參數,均使用${param_name}的形式進行調用。來看下面一段代碼:

    /**
     * 取公共參數 並替換參數,處理${}
     * @param param
     * @return
     */
    protected String getCommonParam(String param) {
        if (stringUtil.isEmpty(param)) {     //stringUtil后續進行說明 return "";
        }
        Matcher m = replaceParamPattern.matcher(param);// 取公共參數正則
        while (m.find()) {
            String replaceKey = m.group(1);
            // 如果公共參數池中未能找到對應的值,該用例失敗。
            Assert.assertNotNull(replaceKey,
                    String.format("格式化參數失敗,公共參數中找不到%s。", replaceKey));
            String value;
            // 從公共參數池中獲取值
            value = getSaveData(replaceKey);
            //如果值不為空,則將參數替換為公共參數池里讀取到的value的值。
            if(null != value) {
                param = param.replace(m.group(), value);
                //如果值為空,則將參數替換為字符串“null”
            }else {
                param = param.replace(m.group(), "null");
            }
        }
        return param;
    }

  這里使用了正則表達式來匹配參數中出現的${XXXX}形式的字符串。這一段的主要思想為,使用定義好的正則表達式來匹配param的字符串,如果匹配的到,則進行循環,把匹配到的第一個字符串(基本就是1個字符串)作為key,然后到saveData的Map中取得對應的值,並返回。

  這樣,我們就實現了使用${param_name}的形式,調用公共參數池的目的。

  那么說完了“取參數”,我們還需要說一下“存參數”。在接口測試執行的過程中,假如我想把某個返回的值作為參數,存入公共參數池中,我們應該怎么做呢?

    /**
     * 提取json串中的值保存至公共池中
     * 
     * @param json
     *            將被提取的json串。
     * @param allSave
     *            所有將被保存的數據:xx=$.jsonpath.xx;將$.jsonpath.
     *            xx提取出來的值存放至公共池的xx中
     */
    protected void saveResult(String json, String allSave) {
        if (null == json || "".equals(json) || null == allSave
                || "".equals(allSave)) {
            return;
        }
        allSave = getCommonParam(allSave);
        String[] saves = allSave.split(";");
        String key, value;
        for (String save : saves) {
            Pattern pattern = Pattern.compile("([^;=]*)=([^;]*)");
            Matcher m = pattern.matcher(save.trim());
            while (m.find()) {
                key = getBuildValue(json, m.group(1));  //getBuildValue的方法后續說明
                value = getBuildValue(json, m.group(2));
                reportUtil.log(String.format("存儲公共參數   %s值為:%s.", key, value));
                saveDatas.put(key, value);
            }
        }
    }

  這里我們在save時,同樣是通過正則表達式來進行匹配,具體的形式類似於 aa=$.Content.User 的形式,即變量名=JSONPath,將JSONPath找到的值來賦此變量,並存儲到公共參數池中。

  這里提到了一個getBuildValue的方法,具體的代碼如下:

/**
     * 獲取格式化后的值
     * 
     * @param sourchJson
     * @param key
     * @return
     */
    private String getBuildValue(String sourchJson, String key) {
        key = key.trim();
        Matcher funMatch = funPattern.matcher(key); //funPattern為函數匹配正則表達式,后續進行說明 if (key.startsWith("$.")) {// 如果為JSONPath,獲取該JSONPath對應的值(對象)    
            Object x = JSONPath.read(sourchJson, key);
       //空值處理
if(x == null) { key = (String)x; }else { key = x.toString(); }
       //如果匹配到的是自定義函數,則先解析該自定義函數的參數,若該自定義函數的參數中有JSONPath,則對該JSONPath取值,並對應轉成字符串對象。 }
else if (funMatch.find()) { String args = funMatch.group(2); String[] argArr = args.split(","); for (int index = 0; index < argArr.length; index++) { String arg = argArr[index]; if (arg.startsWith("$.")) { argArr[index] = JSONPath.read(sourchJson, arg).toString(); } } String value = functionUtil.getValue(funMatch.group(1), argArr); // functionUtil為自定義函數工具類,后續說明 key = stringUtil.replaceFirst(key, funMatch.group(), value); } return key; }

  那么,通過以上的代碼,我們可以較為清晰的看到,我們設計了這個公共參數池,來對全局參數和過程參數進行管理,即可取也可存。方便了在之后的代碼中進行調用。

   在上面的代碼中,我們出現了一個stringUtil的工具類,這算是一個字符串處理工具。請看以下代碼:

public class stringUtil {
    public static boolean isNotEmpty(String str) {
        return null != str && !"".equals(str);
    }

    public static boolean isEmpty(String str) {
        return null == str || "".equals(str);
    }
    
    /**
     * 
     * @param sourceStr 待替換字符串
     * @param matchStr  匹配字符串
     * @param replaceStr  目標替換字符串
     * @return
     */
    public static String replaceFirst(String sourceStr,String matchStr,String replaceStr){
        int index = sourceStr.indexOf(matchStr);
        int matLength = matchStr.length();
        int sourLength = sourceStr.length();
        String beginStr = sourceStr.substring(0,index);
        String endStr = sourceStr.substring(index+matLength,sourLength);
        sourceStr = beginStr + replaceStr + endStr;
        return sourceStr;
    }

}

  這個工具類中,寫了判定字符串是否為空的方法,還有一個替換首個匹配字符串的方法。有興趣的童鞋可以自行繼續擴展。

  
  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM