JMeter-SSE响应数据自动化2.0

结构图

背景

对之前的脚本进行优化

主要是做一些兼容性处理,降低耦合度

优化内容

1.csv文件变量

增加了白名单变量,目标值变量,必须参数变量

2.响应信息获取方式更新

之前是用正则来捕获简单的json格式的响应,响应的格式是固定的。此次更新后使用的是String的spilt()方法来进行信息截取,易读性相较于正则表达式稍好一些

3.白名单变量初始化

只在线程组的第一次HTTP请求的预处理程序中更新

4.降低JSR223后置处理脚本的耦合度

便于后续维护或者更新,兼容性更好

实现思路

只写了一些更新的结构

1.While控制器

来控制从csv数据中读取数据

2.csv数据文件设置


更新了一些新添加的变量

3.JSR223预处理程序

根据csv文件的数据来更新一些HTTP请求中的参数,比如文件、入参等...

java 复制代码
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.ArrayList;

//判断是否需要 files 参数
private Boolean needFiles(String str) {
	if("1".equals(str)) {
		return true;
	}else {
		return false;
	}
}

//设置 files 参数
private void setFiles(String fileParams) {
	try{
		String[] fileList = fileParams.split(";");

		// 创建 JSON 对象数组(List<Map> 格式)
		JSONArray fileParamsArray = new JSONArray();

		for(String s : fileList) {
			fileParamsArray.put(setOneFileParam(s));
		}
		// 存入 vars(JSON 字符串)
		vars.put("fileParam", fileParamsArray.toString());
	} catch (Exception e) {
		log.error("设置 files 参数 失败!", e);
		prev.setSuccessful(false);
	}		
}

//设置 一个 files 参数
private JSONObject setOneFileParam(String fileParam) {
	try {
		//将fileParams转为json格式
		JSONObject jsonResponse = new JSONObject(fileParam);
		// 提取各个参数
		String filexxx= jsonResponse.optString("filexxx", "");
		String filexxx= jsonResponse.optString("filexxx", "");
		Integer filexxx= jsonResponse.optInt("filexxx", 0);  // Integer类型
		String filexxx= jsonResponse.optString("filexxx", "");
		String filexxx= jsonResponse.optString("filexxx", "");

		JSONObject fileObj = new JSONObject();
		fileObj.put("filexxx", filename);
		fileObj.put("filexxx", fileHash);
		fileObj.put("filexxx", filesize);
		fileObj.put("filexxx", extension);
		fileObj.put("filexxx", mimeType);
		return fileObj;
	}catch (Exception e) {
		log.error("setOneFileParam函数设置单个 file 参数 失败!", e);
		prev.setSuccessful(false);
	}
		
}

//初始化白名单
private void initWhite() {
    try {
        String white = vars.get("white");

        if(white != null && !"".equals(vars.get("white"))) {
            String list = vars.get("white");
            String[] ret =  list.split(";");
            Set<String> whiteSet = new HashSet<String>();
            for(String x:ret) {
                whiteSet.add(x);
            }
            vars.putObject("whiteSet",whiteSet);
        }

		// 使用后重置白名单变量,避免影响后续
        vars.put("white","");
    }catch (Exception e) {
        log.error("初始化白名单失败!");
    }
}

try {
	String str = vars.get("needFiles");	
	String fileParams = vars.get("file");

	if(needFiles(str)){
		//需要文件参数
		setFiles(fileParams);
	}else{
		//不需要文件参数,设置为空
		JSONArray fileParamsArray = new JSONArray();
		vars.put("fileParam",fileParamsArray.toString());	
	}

    //初始化白名单
    initWhite();

	
    
} catch (Exception e) {
    log.error("判断是否需要文件参数 失败!", e);
    prev.setSuccessful(false);
}
4.JSR223后置处理脚本

主要处理响应的信息来进行断言操作

java 复制代码
import org.apache.jmeter.samplers.SampleResult;
import org.json.JSONObject;
import org.json.JSONException;

// 每次脚本执行前需要重置的变量
private void init(){
	
    // 添加APPID信息
    vars.put("APPID",vars.get("appId"));

    // 每次重置isExist的值,避免上次结果影响本次
    vars.put("isExist", "true");

    // 每次重置断言输出信息
    vars.put("response_type","");
    vars.put("error_msg", "");
    vars.put("actual_msg", "");
}

// 判断是否是流式响应
private Boolean isStreamingResponse(String response) {
    return response.contains("data: {");
}

// 非流式响应处理
private void handleNonStreamingResponse(String response, SampleResult prev) throws Exception {
    JSONObject jsonResponse = new JSONObject(response);
    String msg = jsonResponse.get("msg");

    if ("不存在".equals(msg)) {
        setAssertMsg("不存在",msg);
    } else {
        setAssertMsg("非流式响应,未知错误",msg);
    }
}

// 处理SSE响应数据,以data: 为分隔符,输出结果到String[] 中
private String[] splitResponse(String resp) {
   try {
        return resp.split("data: ");
   }catch(Exception e) {
        log.error("拆分resp为String数组失败!" + vars.get("appName"));
   }
}

// 获取event信息
private String getEvent(String resp) {
    try {
        String ret = resp.substring(resp.indexOf("\"", 8)+1, resp.indexOf("\"", 12));
        return ret;
    }catch(Exception e) {
        log.error("获取event的字段内容失败!");
        return "Unknow";
    }
}

// 处理error响应
private void errorResp(String resp) {
    try{
        JSONObject jsonResponse = new JSONObject(resp);
        String errorMsg = jsonResponse.get("message");
        setAssertMsg("执行失败",errorMsg);
    }catch(Exception e) {
        log.error("处理 error 响应信息失败");
    }
}

// 判断有无特定target
private Boolean hasTarget(String resp) {
    String targetStr = vars.get("target");
    // 每次执行后重置target,避免影响下次target的值
    vars.put("target", "");
    
    return resp.contains(targetStr);
}

// 断言参数设置
private void setAssertMsg(String response_type,String error_msg){
    vars.put("response_type",response_type);
    vars.put("error_msg", error_msg);
    vars.put("isExist", "false");
}
private void setAssertMsg(String resp){
    //获取answer中的信息,实际msg
    JSONObject jsonResp = new JSONObject(resp);
    String answer = jsonResp.get("xxx")
                            .get("xxx")
                            .optString("具体信息");
    vars.put("response_type","无目标值");
    vars.put("actual_msg", answer);
    vars.put("isExist", "false");
}

// 是否需要判断 特定target
private Boolean needCheckTarget(String resp) {
    if(vars.get("target") != null || !"".equals(vars.get("target"))) {
        // 有target,需要判断特定target
        return hasTarget(resp);
    }else {
        // 无需判断特定target
        return true;
    }
}

// 过滤器,过滤白名单
private void filter(String resp) {
    try {
        Set<String> whiteSet = vars.getObject("whiteSet");
        String appId = vars.get("APPID");
        if(whiteSet.contains(appId)) {
            vars.put("isExist", "true");
        }else {
            // 非白名单
            errorResp(resp);
        }
    } catch (Exception e) {
        setAssertMsg("过滤器失效!","过滤器失效!");
        log.warn("过滤白名单失败!");
    }
}

/**
    每次执行后,处理变量
    避免下次空变量的值 受上次的影响
    变量:xxx
*/
private void afterHandle(){
    vars.put("xxx","");
}


SampleResult prev = ctx.getPreviousResult();

String response = prev.getResponseDataAsString();

// 执行前重置变量
init();

// 判断是不是SSE响应
try {
    if (!isStreamingResponse(response)) {
        // 非SSE响应
        handleNonStreamingResponse(response, prev);
    } else {
        // SSE响应
        // 拆分
        String[] respArray = splitResponse(response);
        // 获取event,进行判断
        String event = getEvent(respArray[respArray.length - 1]);
        if("message_end".equals(event)) {
            if(needCheckTarget(respArray[respArray.length - 2])){
                vars.put("isExist", "true");
            }else {
                // 无目标字段,更新断言信息
                setAssertMsg(respArray[respArray.length - 2]);
            }
        }else if("error".equals(event)) {
            // 有报错,进入过滤器,过滤白名单
            filter(respArray[respArray.length - 1]);
        }else if("Unknow".equals(event)) {
            // 获取event的字段内容失败!
            setAssertMsg("响应异常!","获取event的字段内容失败!");
        }else {
            // 未知错误
            setAssertMsg("处理SSE响应异常!!!","处理SSE响应异常!!!");
        }
    }
} catch (Exception e) {
    log.error("处理响应失败!", e);
    setAssertMsg("处理响应异常!","处理响应异常!");
    prev.setSuccessful(false);
}finally {
    afterHandle();
}
相关推荐
半导体守望者3 小时前
ADVANTEST R3764 66 R3765 67爱德万测试networki connection programming网络程序设计手册
经验分享·笔记·功能测试·自动化·制造
东方佑6 小时前
使用 Python 自动化 Word 文档样式复制与内容生成
python·自动化·word
太阳之神aboluo8 小时前
压测软件-Jmeter
java·运维·jmeter
三千花灯8 小时前
jmeter之导出接口
jmeter
文人sec8 小时前
性能测试-jmeter实战2
jmeter
程序媛_8 小时前
【JMeter】后置处理器 - 提取器
jmeter
程序员三藏8 小时前
如何使用Jmeter进行压力测试?
自动化测试·软件测试·python·测试工具·jmeter·测试用例·压力测试
新加坡内哥谈技术10 小时前
Meta计划借助AI实现广告创作全自动化
运维·人工智能·自动化
集成显卡19 小时前
PlayWright | 初识微软出品的 WEB 应用自动化测试框架
前端·chrome·测试工具·microsoft·自动化·edge浏览器