JMeter有关JAR依赖异常问题

最近在测试压测平台的时候,老是会出现JAR依赖的冲突问题,但是实在也找不到原因,感觉也可能是环境变量有问题,但是确认过也不是,手动执行也会报错,后来换了种实现方式,记录一下

先说一下之前的编码实现

创建用例;关联JMX脚本;关联CSV文件,依赖JMX脚本,修改脚本里文件路径;关联JAR文件,不依赖JMX脚本,在执行压测运行JMX脚本时,修改jmeter.properties配置里JAR自定义依赖路径

UntitledImage

这里更新jar配置应该是在用户执行用例的时候进行,原因是如果关联jar的时候就去修改配置,而该用例却并没有执行,其它人却去执行了其他用例,会导致jar配置不正确而执行异常;根本原因就是修改的配置是jmeter的公共配置,因此不太完美

@Override
public void updateJarDependency(String testCaseFilePath) {
String regex = "^plugin_dependency_paths=(.*)";
String masterJmeterHomeBin = configService.getByField(JMeterUtil.MASTER_JMETER_HOME_BIN);
String jmerterPropertiesFilePath = masterJmeterHomeBin + "/jmeter.properties";
/** 转义 */
String jarFilePath = testCaseFilePath + "jar";
JMeterUtil jmeter = new JMeterUtil();
log.info("更新master节点JAR配置, jmerterPropertiesFilePath: {}, jarFilePath: {}", jmerterPropertiesFilePath, jarFilePath);
jmeter.write(jmerterPropertiesFilePath, jmeter.read(jmerterPropertiesFilePath, regex, jarFilePath));

/** 每个启用的slave节点也需要修改,远程新修改配置 */
List<NodeDO> enableNodeList = nodeService.getEnableNodeList();
log.info("更新slave节点JAR配置, 已启用的slave节点: {}", JSON.toJSONString(enableNodeList, true));
if (!CollectionUtils.isEmpty(enableNodeList)) {
for (NodeDO node : enableNodeList) {
/** 每个slave节点jar配置都修改,路径和master一致 */
SSHUtils ssh = new SSHUtils(node.getHost(), node.getPort(), node.getUsername(), node.getPassword());
String command = "sed -i 's/^plugin_dependency_paths=.*/plugin_dependency_paths="
+ jarFilePath.replace("/", "\\/") + "/g' " + jmerterPropertiesFilePath;
log.info("更新JAR配置, command: {}", command);
ssh.execCommand(command);
}
}
}

 

但出现JAR依赖问题后,考虑换了一种方式

创建用例;关联JMX脚本;关联CSV文件,依赖JMX脚本,修改脚本里文件路径;关联JAR文件,依赖JMX脚本,修改脚本里JAR包的classpath

UntitledImage

至于具体修改JMX里哪个地方,可以手动GUI JMeter里新增一个jar路径,然后做一个diff,其实就是下面这里配置,因此可以将以来的jar路径都写在jmx此处即可

UntitledImage

具体实现,先读取JMX脚本,也就是一个xml文件

public void updateJmxJarFilePath(String jmxFilePath, String jarFilePath) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(new File(jmxFilePath));
} catch (DocumentException e) {
e.printStackTrace();
}
Element root = document.getRootElement();
updateJARFilePath(jmxFilePath, document, root, jarFilePath);
}

写一个递归,遍历xml里所有的节点,在TestPlan里匹配名称为TestPlan.user_define_classpath的即可,因为压测平台最终一个用例会将所有以来的jar配置在一个路径下,配置在这里即可

public void updateJARFilePath(String jmxFilePath, Document document, Element root, String jarFilePath) {

for (Element element : root.elements()) {
/** jmx脚本文件的CSV配置节点 */
if ("TestPlan".equals(element.getName())) {
for (Element prop : element.elements()) {
if ("TestPlan.user_define_classpath".equals(prop.attributeValue("name"))) {
prop.setText(jarFilePath);
writeXML(document, jmxFilePath);
}
}
break;
} else {
updateJARFilePath(jmxFilePath, document, element, jarFilePath);
}
}
}

这样,在用例脚本关联jar的时候,就可以调用更新操作

 

同样的道理,对于csv文件的关联

UntitledImage

通过CSVDataSet匹配节点名称,然后根据传入的csv名称匹配testname,修改filename也就是csv的路径即可,简单编码如下

private void updateCSVFilePath(String jmxFilePath, Document document, Element root, String csvFile, String csvFilePath) {

for (Element element : root.elements()) {
/** jmx脚本文件的CSV配置节点 */
if ("CSVDataSet".equals(element.getName())
&& csvFile.equals(element.attributeValue("testname"))) {
for (Element prop : element.elements()) {
if ("filename".equals(prop.attributeValue("name"))) {
prop.setText(csvFilePath);
//System.out.println(prop.getText());
writeXML(document, jmxFilePath);
}
}
break;
} else {
/** 递归找到对应的csv文件所在的地方 */
updateCSVFilePath(jmxFilePath, document, element, csvFile, csvFilePath);
}
}
}

OVER

发表评论