Jmeter入门实战(二)如何使用Jmeter的BeanShell断言,把响应数据中的JSON跟数据库中的记录对比

很多时候我们需要把Response Data取到的 Json 字符串跟数据库里的对比,来验证接口的正确性,使用Beanshell断言可以比较灵活的实现这个需求。

Beanshell是一种类似JAVA的脚本语言,可以直接调用外部的jar包,可以拿现成的json解析包来用,所以笔者选择了这个方法。实现的思路是


1、历史数据存储到MYSQL数据库里,

2、Jmeter读取参数化的CSV文件,把测试用例都存入CSV文件一次执行,

3、CSV文件和数据库中数据用ID关联,

4、每次断言都用BeanShell使用JDBC连接MYSQL库,使用测试用例的ID查出MYSQL中的数据

5、调用GSON的解析JSON方法,对比两个数据,进行断言


BeanShell在Jmeter中的使用可以参考这篇文章,https://www.blazemeter.com/blog/queen-jmeters-built-componentshow-use-beanshell   在这里就不多做介绍了。

GSON是Google的一个解析JSON的工具,笔者不太懂java,但是JSON字符串的对比不能直接用字符串比较,所以引用了这个包,然后调用了GSON的JsonObject.equals()方法,来判断两个JSON的内容是否一样。大家可以多研究下,最好能完成例如断言失败时打印内容不同的KEY等功能。

一、在Jmeter中添加BeanShell断言


<think>好的,用户的问题是在JMeter使用Beanshell实现逐行比对CSV文件和数据库查询结果。我需要结合之前的回答和用户提供的引用内容来给出解决方案。首先,用户提到的引用[1]是关于数据库连接的,引用[2]涉及将数据写入CSV,引用[3]和[4]是关于Beanshell断言进行JSON数据库对比的。这些引用内容可能对用户有帮助,但需要整合到当前的问题中。用户的需求是逐行比对CSV和数据库结果。之前的回答中已经提到使用CSVData SetConfig读取数据,JDBC请求获取数据库结果,然后用Groovy脚本进行比对。但用户现在希望用Beanshell实现,可能需要调整之前的方案。首先,我需要确定如何用Beanshell处理CSV读取和数据库查询。可能需要在Beanshell前置处理器或后置处理器中编写代码。例如,读取CSV文件可以使用Java的FileReader和BufferedReader,逐行读取并存储到变量中。数据库连接部分,引用[1]中的代码示例展示了如何连接DB2,但用户可能需要适配其他数据库,比如Oracle或MySQL,需要根据具体情况调整驱动和URL。然后,数据库查询结果需要CSV数据逐行比较。引用[4]中的代码展示了如何将数据库结果拼接成JSON字符串并响应对比,但这里需要改为逐行比对CSV内容。可能需要将CSV的每一行和数据库的每一行提取出来,逐个字段比较。 需要注意线程安全和变量共享的问题。例如,CSV DataSet Config默认是每个线程独立的,但如果是多线程测试,可能需要使用共享模式。或者,在Beanshell中读取整个CSV文件到内存,然后按行索引进行比较,确保每个线程处理正确的行。 另外,异常处理和日志记录也很重要。引用[4]中的代码使用了Failure和FailureMessage变量来标记断言结果,这可以在Beanshell断言使用。同时,需要处理可能的异常,如数据库连接失败、文件读取错误等,并记录详细的错误信息。还需要考虑性能问题,特别是当CSV文件较大时。逐行读取和处理可能会影响测试性能,可能需要优化代码,比如使用缓冲区读取文件,或者分批处理数据。 最后,生成相关问题需要考虑用户可能的后续需求,比如如何处理特殊字符、加密连接、分布式执行等,这些问题在之前的回答中已经部分涉及,需要根据当前解决方案的上下文进行补充。</think>### JMeter使用Beanshell实现CSV数据库逐行比对的方法 --- #### 一、核心实现步骤 1. **CSV数据加载** - **文件读取**:使用`BeanShell PreProcessor`加载CSV文件 ```java import java.io.*; BufferedReader br = new BufferedReader(new FileReader("test.csv")); String line; ArrayList<String> csvData = new ArrayList(); while ((line = br.readLine()) != null) { csvData.add(line); } br.close(); vars.putObject("csvData", csvData); // 存储到JMeter变量[^2] ``` 2. **数据库查询执行** - **JDBC连接配置**:通过`JDBC Connection Configuration`设置参数[^1] ```properties JDBC URL: jdbc:mysql://host:port/db Username: root Password: 123456 ``` - **结果集获取**:在`BeanShell PostProcessor`中执行查询 ```java import java.sql.*; Connection conn = DriverManager.getConnection(vars.get("dbUrl"), vars.get("dbUser"), vars.get("dbPass")); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM students"); ArrayList<String> dbData = new ArrayList(); while (rs.next()) { String row = rs.getString(1) + "," + rs.getString(2); dbData.add(row); } rs.close(); vars.putObject("dbData", dbData); ``` 3. **逐行比对逻辑** ```java ArrayList csvList = vars.getObject("csvData"); ArrayList dbList = vars.getObject("dbData"); // 行数校验 if (csvList.size() != dbList.size()) { Failure = true; FailureMessage = "行数不匹配: CSV=" + csvList.size() + " DB=" + dbList.size(); } // 逐行数据比对 for (int i=0; i<csvList.size(); i++) { String csvLine = (String)csvList.get(i); String dbLine = (String)dbList.get(i); if (!csvLine.equals(dbLine)) { log.error("第" + (i+1) + "行不一致:\nCSV:" + csvLine + "\nDB:" + dbLine); Failure = true; FailureMessage = "数据差异详见日志"; break; } } ``` --- #### 、关键技术要点 1. **字段映射控制** - 通过`ResultSetMetaData`动态获取字段数: ```java ResultSetMetaData meta = rs.getMetaData(); int colCount = meta.getColumnCount(); // 获取列数[^4] ``` 2. **特殊字符处理** - CSV中逗号转义处理: ```java String escapedLine = line.replaceAll(",", "\\,"); // 转义逗号 ``` 3. **性能优化** - 使用哈希值快速比对: ```java String csvHash = org.apache.commons.codec.digest.DigestUtils.md5Hex(csvLine); String dbHash = org.apache.commons.codec.digest.DigestUtils.md5Hex(dbLine); if (!csvHash.equals(dbHash)) { /* 详细比对 */ } ``` --- #### 三、验证调试 | 验证方式 | 实现方法 | |-------------------|--------------------------------------------------------------------------| | 数据完整性检查 | 添加`Debug Sampler`查看`csvData`和`dbData`变量内容 | | 差异定位 | 使用`View Results Tree`查看断言失败详情 | | 性能监控 | 通过`jp@gc - PerfMon`监控内存使用情况,防止大数据量时OOM | --- #### 四、扩展应用场景 1. **动态字段忽略** ```java // 配置忽略字段索引 String ignoreCols = "3,5"; if (i != 3 && i != 5) { /* 执行比对 */ } ``` 2. **容错比对模式** ```java // 允许数值型字段±1误差 double csvVal = Double.parseDouble(csvField); double dbVal = Double.parseDouble(dbField); if (Math.abs(csvVal - dbVal) > 1) { /* 标记差异 */ } ``` --- ### 示例代码完整结构 ```java // BeanShell断言完整实现 try { // 步骤1: 读取CSV BufferedReader br = new BufferedReader(new FileReader("data.csv")); ArrayList<String> csvList = new ArrayList(); String line; while ((line = br.readLine()) != null) { csvList.add(line.replaceAll(",", "|")); // 统一分隔符 } br.close(); // 步骤2: 查询数据库 Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456"); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT CONCAT_WS('|', id, name) FROM users"); ArrayList<String> dbList = new ArrayList(); while (rs.next()) { dbList.add(rs.getString(1)); } rs.close(); conn.close(); // 步骤3: 逐行比对 if (csvList.size() != dbList.size()) { throw new Exception("行数不一致"); } for (int i=0; i<csvList.size(); i++) { if (!csvList.get(i).equals(dbList.get(i))) { log.error("差异行号:" + (i+1)); throw new Exception("数据内容不一致"); } } } catch (Exception e) { Failure = true; FailureMessage = e.getMessage(); } ``` ---
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值