java使用jmeter生成jmx之導入cvs文件


上一篇:java使用jmeter生成jmx文件並運行

前言:
繼上一篇,使用java生成jmx文件,並運行,但是我們發現,傳遞的數據只有一個請求體,也就是當不設置循環調用的時候,該接口之調用一次

那么有沒有什么辦法,我們根據請求體傳遞的參數不同來調用多次?

當然有了,我們使用jmeter自帶的導入csv文件功能,我們將每次請求的不同的請求體放入到csv文件中

創建csv文件

文件內容如下圖所示:

我們使用java代碼生成。

package com.yiyang.myfirstspringdemo.utils;

import com.yiyang.myfirstspringdemo.model.Passenger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.yiyang.myfirstspringdemo.service.JemterTest.JMETER_ENCODING;
import static com.yiyang.myfirstspringdemo.service.JemterTest.NUMBER_THREADS;

/**
* @Author 劉翊揚
* @Date 2020/10/11 3:12 下午
* @Version 1.0
*/
@Slf4j
@Component
public class CVSUtils {

   static String format = "\"%s\"";

   /**
    * 生成為CVS文件
    *
    * @param exportData 源數據List
    * @param outPutPath 文件路徑
    * @param fileName   文件名稱
    * @return
    */
   private static File createCSVFile(List<List<String>> exportData, String outPutPath, String fileName) {
       File csvFile = null;
       BufferedWriter csvFileOutputStream = null;
       try {
           File file = new File(outPutPath);
           if (!file.exists()) {
               if (file.mkdirs()) {
                   log.info("創建cvs文件成功");
               } else {
                   log.error("創建cvs文件失敗");
               }
           }
           // 定義文件名格式並創建
           csvFile = File.createTempFile(fileName, ".csv", new File(outPutPath));
           csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile)));
           for (List<String> exportDatum : exportData) {
               writeRow(exportDatum, csvFileOutputStream);
               csvFileOutputStream.newLine();
           }
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           if (csvFileOutputStream != null) {
               try {
                   csvFileOutputStream.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
           // 如果臨時文件,不需要在使用完成之后,記得刪除。我這里就先不刪除了。
           // csvFile.delete();
           // csvFile.deleteOnExit();
       }
       return csvFile;
   }

   /**
    * 寫一行數據
    * @param row       數據列表
    * @param csvWriter
    * @throws IOException
    */
   private static void writeRow(List<String> row, BufferedWriter csvWriter) throws IOException {
       for (String data : row) {
           csvWriter.write(new String(data.getBytes(JMETER_ENCODING), JMETER_ENCODING));
           // csvWriter.write(data);
       }
   }

   /***
    * 將json弄成csv文件可以識別的,保證這個請求體(json格式)在同一列
    * @param object
    * @return
    * @throws IllegalAccessException
    */
   private static String cvsFormat(Object object) throws IllegalAccessException {
       StringBuilder sb = new StringBuilder();
       sb.append(String.format(format, "{"));
       Class<?> aClass = object.getClass();
       Field[] declaredFields = aClass.getDeclaredFields();
       int i = 0;
       for(Field field : declaredFields) {
           field.setAccessible(true);
           Object value = field.get(object);
           if (value == null) {
               continue;
           }
           String name = field.getName();
           sb.append(String.format(format, name));
           sb.append(String.format(format, ":"));
           sb.append(String.format(format, value));
           if (i < declaredFields.length - 1) {
               sb.append(String.format(format, ","));
           }
           i++;
       }
       sb.append(String.format(format, "}"));
       return sb.toString();
   }


   public static File getCsvPath () {
       String outFile = "/Users/liufei/Downloads/jmter";
       String filename = "my_replay_data";
       List<List<String>> listList = new ArrayList<List<String>>();
       List<String> list = null;
       list = new ArrayList<>();//一個List為一行
       // 標題
       list.add("body");
       listList.add(list);

       // 內容
       int count = NUMBER_THREADS;
       for (int i = 0; i < count; i++){
           List<String> colList = new ArrayList<>();
           Passenger passenger = new Passenger();
           String uuId = UUID.randomUUID().toString().substring(0, 8);
           passenger.setName("劉翊揚_" + uuId);
           passenger.setPassword("123456_" + uuId);
           String json = null;
           try {
               json = cvsFormat(passenger);
           } catch (IllegalAccessException e) {
               e.printStackTrace();
           }
           colList.add(json);
           listList.add(colList);
       }
       return createCSVFile(listList, outFile, filename);
   }

   /***
    * 獲取文件的行數
    * @param file
    * @return
    * @throws IOException
    */
   public static int getTotalLines(File file) throws IOException {
       long startTime = System.currentTimeMillis();
       FileReader in = new FileReader(file);
       LineNumberReader reader = new LineNumberReader(in);
       reader.skip(Long.MAX_VALUE);
       int lines = reader.getLineNumber();
       reader.close();
       long endTime = System.currentTimeMillis();

       System.out.println("統計文件行數運行時間: " + (endTime - startTime) + "ms");
       return lines;
   }
}

注意:因為請求體中含有中文,所以為了避免亂碼:需要保持編碼一樣(樓主使用的是UTF-8)

  1. 首先在寫入csv文件設置編碼。
  2. jemter解析csv文件時,需要設置編碼
  3. http發送請求時,需要設置內容編碼

以上三個保持一致就不會出現亂碼了。

詳細內容:請查看這篇文章

生成的csv,在jmx中指定需要導入csv文件的路徑

我們修改JmterTest.java類中的run方法。(在上一篇文章中)

private static void run() {

        String url = "localhost";
        String port = "8088";
        String api = "/mongo/insert";
        /** 由於csv文件的請求體列中標題是body */
        String request = "${body}";

        String jemterHome = "/Users/liufei/Downloads/apache-jmeter-5.3";
        JMeterUtils.setJMeterHome(jemterHome);
        JMeterUtils.loadJMeterProperties(JMeterUtils.getJMeterBinDir() + "/jmeter.properties");
        //JMeterUtils.initLocale();

        // 獲取TestPlan
        TestPlan testPlan = getTestPlan();

        // 獲取設置循環控制器
        LoopController loopController = getLoopController();


        // 獲取Http請求信息
        HTTPSamplerProxy httpSamplerProxy = getHttpSamplerProxy(url, port, api, request);

        // 獲取結果:如匯總報告、察看結果樹
        List<ResultCollector> resultCollector = getResultCollector(replayLogPath);

        // 獲取CVSData設置
        /** === 主要是這里的變化 ====== */
        File cvsPath = CVSUtils.getCsvPath();
        int number = 0;
        try {
             // 去掉body標題列
             number = CVSUtils.getTotalLines(cvsPath) - 1;
        } catch (IOException e) {
            e.printStackTrace();
        }
        CSVDataSet csvDataSet = getCSVDataSet(cvsPath.getAbsolutePath());

        // 獲取線程組
        ThreadGroup threadGroup = getThreadGroup(loopController, number);

        // 獲取設置吞吐量
        ConstantThroughputTimer constantThroughputTimer = getConstantThroughputTimer(20);

        // 獲取請求頭信息
        HeaderManager headerManager = getHeaderManager();

        HashTree fourHashTree = new HashTree();
        resultCollector.stream().forEach(item -> fourHashTree.add(item));
        fourHashTree.add(headerManager);
        /** 將csvDataSet添加進去 */
        fourHashTree.add(csvDataSet);

        HashTree thirdHashTree = new HashTree();
        // 注意:設置吞吐量需要和Http請求同一級,否則無效
        thirdHashTree.add(constantThroughputTimer);
        thirdHashTree.add(httpSamplerProxy, fourHashTree);

        HashTree secondHashTree = new HashTree();
        secondHashTree.add(threadGroup, thirdHashTree);


        HashTree firstTreeTestPlan = new HashTree();
        firstTreeTestPlan.add(testPlan, secondHashTree);

        try {
            SaveService.saveTree(firstTreeTestPlan, new FileOutputStream(jmxPath));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 第一種方式:運行
        StandardJMeterEngine jMeterEngine = new StandardJMeterEngine();
        jMeterEngine.configure(firstTreeTestPlan);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        jMeterEngine.run();
        System.out.println("運行成功!!!");

        // 使用命令
       /* String command = JMeterUtils.getJMeterBinDir() + "/jmeter -n -t " + jmxPath + " -l /Users/liufei/Downloads/jmter/replay_result.jtl";
        Runtime.getRuntime().exec(command);
        System.out.println(command);*/
    }

主要修改的有三個地方:
第7行和、第29 ~ 38行、52行


免責聲明!

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



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