前言:之前詳解過通過jmeter生成的csv文件,解析csv存入DB,這個有弊端
第一:需獨立創建一個job
第二:需按照一定規范輸出
因此,放棄解析csv方式,直接解析自動化生成的原始jtl文件並集成到ant-jmeter中,不在獨立一個job而是跟項目在一起,直接在持續集成過程中insert DB。
解析jtl文件與前面介紹的javamail思路相同(若想了解 http://www.cnblogs.com/nzg-noway/p/6909821.html )
insert DB依然是2張表,詳情表和統計表
Step1:具體insert操作就是jdbc鏈接和sql操作。如下:
注意:
1.把jdbc配置項拉取到配置文件,支持靈活可變
2.創建表結構(根據業務創建索引、唯一等)
package org.programmerplanet.ant.taskdefs.jmeter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.Date; public class InsertDB { public static String currTime(){ //設置日期格式 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // new Date()為獲取當前系統時間 String now = df.format(new Date()); return now; } //詳情數據 static public void insertDetailDB(String BuildNum,String Module,String InterfaceName,String CaseName,String Result,String databaseName,String userName, String password,String connUrl){ try { Class.forName("com.mysql.jdbc.Driver"); // String databaseName = "AutoResult"; // String userName = "root"; // String password = "trend520"; // String connUrl = "jdbc:mysql://10.64.66.227:3306/"; Connection conn = DriverManager.getConnection(connUrl + databaseName, userName, password); PreparedStatement st = null; String currTime = InsertDB.currTime(); // System.out.println("當前詳情入庫時間:"+currTime); Statement stmt = conn.createStatement(); // 創建數據庫中的表, String sql = "create table if NOT EXISTS Auto_Detail" + "(id int NOT NULL auto_increment primary key ," + "BuildNum varchar(20) ," + "Module varchar(100)," + "InterfaceName varchar(100)," + "CaseName varchar(100) ," + "Result varchar(10)," + "CreateTime varchar(30) NOT NULL DEFAULT '"+currTime+"'," + " UNIQUE INDEX(BuildNum,Module,InterfaceName,CaseName,CreateTime))"; // System.out.println("輸出sql創建表語句:"+sql); int result = stmt.executeUpdate(sql); if (result != -1) { sql = "insert into Auto_Detail(BuildNum,Module,InterfaceName,CaseName,Result,CreateTime) values(?,?,?,?,?,?) " + "ON DUPLICATE KEY UPDATE Result=?"; st = conn.prepareStatement(sql); st.setString(1, BuildNum); //存入過程大寫轉小寫 st.setString(2, Module.toLowerCase()); st.setString(3, InterfaceName.toLowerCase()); st.setString(4, CaseName.toLowerCase()); //存入執行結果true或者false轉為小寫 st.setString(5, Result.toLowerCase()); st.setString(6, currTime); st.setString(7, Result.toLowerCase()); st.executeUpdate(); sql = "SELECT * FROM Auto_Detail"; // System.out.println(stmt.executeQuery(sql)); ResultSet rs = stmt.executeQuery(sql); // System.out.println("id\tBuildNum\tModule\tInterfaceName\tCaseName\tResult\tCreatTime"); while (rs.next()) { // System.out.println(rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString(4) + "\t" + rs.getString(5) + "\t" + rs.getString(6) + "\t" + rs.getString(7)); } } conn.close(); } catch (Exception e) { e.printStackTrace(); } } //統計數據 static public void insertStatisticsDB(String BuildNum,String Module,int CaseNum,int FailNum,String Rate,String databaseName,String userName, String password,String connUrl){ try { Class.forName("com.mysql.jdbc.Driver"); // String databaseName = "AutoResult"; // String userName = "root"; // String password = "trend520"; // String connUrl = "jdbc:mysql://10.64.66.227:3306/"; Connection conn = DriverManager.getConnection(connUrl + databaseName, userName, password); PreparedStatement st = null; String currTime = InsertDB.currTime(); // System.out.println("當前統計入庫時間:"+currTime); Statement stmt = conn.createStatement(); // 創建數據庫中的表, String sql = "create table if NOT EXISTS Auto_Statistics" + "(id int NOT NULL auto_increment primary key ," + "BuildNum varchar(20) ," + "Module varchar(100)," + "CaseNum int," + "FailNum int ," + "Rate varchar(20)," + "CreateTime varchar(30) NOT NULL DEFAULT '"+currTime+"'," + " UNIQUE INDEX(BuildNum,Module,CreateTime))"; // System.out.println("輸出sql創建表語句:"+sql); int result = stmt.executeUpdate(sql); if (result != -1) { sql = "insert into Auto_Statistics(BuildNum,Module,CaseNum,FailNum,Rate,CreateTime) values(?,?,?,?,?,?) " + "ON DUPLICATE KEY UPDATE CaseNum=?,FailNum=?,Rate=?"; // System.out.println("查看統計sql:"+sql); st = conn.prepareStatement(sql); st.setString(1, BuildNum); //存入過程大寫轉小寫 st.setString(2, Module.toLowerCase()); st.setInt(3, CaseNum); st.setInt(4, FailNum); st.setString(5, Rate); st.setString(6, currTime); st.setInt(7, CaseNum); st.setInt(8, FailNum); st.setString(9, Rate); st.executeUpdate(); sql = "SELECT * FROM Auto_Statistics"; // System.out.println(stmt.executeQuery(sql)); ResultSet rs = stmt.executeQuery(sql); // System.out.println("id\tBuildNum\tModule\tCaseNum\tFailNum\tRate\tCreatTime"); while (rs.next()) { // System.out.println(rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString(4) + "\t" + rs.getString(5) + "\t" + rs.getString(6) + "\t" + rs.getString(7)); } } conn.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args){ insertDetailDB("9.8.1001", "test", "aaa", "bbb", "true","AutoResult","root","trend520","jdbc:mysql://10.64.66.227:3306/"); } }
step2:拆分和獲取insert DB的參數
注意:
1.命名規范(滿足module和interface,由於統計jdbc請求因此,module和table也可以)
2.參數拆分和獲取依據
3.數據統計計算
4.由於業務方面buildNum需要,因此參數值獲取時需要把buildNum丟掉
package org.programmerplanet.ant.taskdefs.jmeter; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import javax.mail.MessagingException; import java.io.UnsupportedEncodingException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; public class DBTask extends Task{ private String resultLog=null; File resultLogFile; // private String databaseName=null; private String userName=null; private String password=null; private String connUrl=null; /* String databaseName = "AutoResult"; String userName = "root"; String password = "xxxxxx"; String connUrl = "jdbc:mysql://10.64.66.227:3306/";*/ //jtl文件 public void setResultLog(String resultLog) { this.resultLog = resultLog; } public String getResultLog() { return resultLog; } public void setdatabaseName(String databaseName) { this.databaseName = databaseName; } public String getdatabaseName() { return databaseName; } public void setuserName(String userName) { this.userName = userName; } public String getuserName() { return userName; } public void setpassword(String password) { this.password = password; } public String getpassword() { return password; } public void setconnUrl(String connUrl) { this.connUrl = connUrl; } public String getconnUrl() { return connUrl; } /** * @see org.apache.tools.ant.Task#execute() * task執行的入口 */ public void execute() throws BuildException { System.out.println("開始執行插入數據庫task"); resultLogFile = new File(System.getProperty("user.dir")+resultLog); if (resultLogFile.exists()){ System.out.println("開始解析數據插入DBresultLog"); try { analyseResultLog(); } catch (MessagingException e) { e.printStackTrace(); } }else{System.out.println("resultLog不存在,請檢查!");} } private class Entity { int successNum=0; int failNum=0; } private void analyseResultLog() throws BuildException, MessagingException { String fullTitile= null; String BuildNum= null; String Module= null; String InterfaceName= null; String InterfaceName_1= null; String CaseName= null; String Result= null; String rate= null; int CaseTotalNum=0; int FailNumber=0; List<String> ModuleArray = new ArrayList<String>(); List<String> InterfaceNameArray = new ArrayList<String>(); List<String> CaseNameArray = new ArrayList<String>(); List<String> ResultArray = new ArrayList<String>(); HashMap<String,Entity> data = new HashMap<String,Entity>(); DecimalFormat df = new DecimalFormat("0.00"); try { FileInputStream fis = new FileInputStream(System.getProperty("user.dir")+resultLog); InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { if (line.contains("<httpSample")==true||line.contains("<sample t=")==true) { fullTitile = line.split("\"")[13]; Result = line.split("\"")[11]; ResultArray.add(Result); //獲取構建版本號 if(fullTitile.contains("BuildNum")==true){ BuildNum = fullTitile.substring(fullTitile.toLowerCase().indexOf("module")+6,fullTitile.indexOf("BuildNum")).trim(); } if(fullTitile.toLowerCase().contains("module")==true){ Module = fullTitile.substring(0,fullTitile.toLowerCase().indexOf("module")).trim(); ModuleArray.add(Module); if(fullTitile.toLowerCase().contains("interface")==true){ InterfaceName_1 = fullTitile.substring(fullTitile.toLowerCase().indexOf("module")+6,fullTitile.toLowerCase().indexOf("interface")).trim(); if(InterfaceName_1.contains("BuildNum")==true){ InterfaceName = InterfaceName_1.substring(InterfaceName_1.indexOf("BuildNum")+8); }else { InterfaceName = InterfaceName_1; } // System.out.println("輸出接口名稱:"+InterfaceName); CaseName = fullTitile.substring(fullTitile.toLowerCase().indexOf("interface")+9).trim(); // System.out.println("輸出用例名稱:"+CaseName); }else if(fullTitile.toLowerCase().contains("table")==true){ InterfaceName = fullTitile.substring(fullTitile.toLowerCase().indexOf("module")+6,fullTitile.indexOf("table")).trim(); CaseName = fullTitile.substring(fullTitile.toLowerCase().indexOf("table")+5).trim(); } InterfaceNameArray.add(InterfaceName); CaseNameArray.add(CaseName); if(data.get(Module) == null){ Entity entity = new Entity(); if (line.indexOf(" s=\"true\"") !=-1) { entity.successNum = 1; }else{ entity.failNum = 1; } data.put(Module, entity); }else{ Entity entity = data.get(Module); if (line.indexOf(" s=\"true\"") !=-1) { entity.successNum += 1; }else{ entity.failNum += 1; } data.put(Module, entity); } } } } // System.out.println("ModuleArray名稱為:"+ModuleArray+ModuleArray.size()); // System.out.println("InterfaceNameArray名稱為:"+InterfaceNameArray+InterfaceNameArray.size()); // System.out.println("CaseNameArray名稱為:"+CaseNameArray+CaseNameArray.size()); // System.out.println("ResultArray名稱為:"+ResultArray+ResultArray.size()); System.out.println("構建日期為:"+InsertDB.currTime()); System.out.println("構建版本為:"+BuildNum); for(int i=0;i<InterfaceNameArray.size();i++){ Module=ModuleArray.get(i); InterfaceName=InterfaceNameArray.get(i); CaseName=CaseNameArray.get(i); Result=ResultArray.get(i); InsertDB.insertDetailDB(BuildNum, Module, InterfaceName, CaseName, Result,databaseName,userName,password,connUrl); } System.out.println("場景詳情數據插入DB成功"); Iterator<String> iterator = data.keySet().iterator(); while(iterator.hasNext()){ Module = iterator.next(); Entity entity = data.get(Module); CaseTotalNum =entity.successNum+entity.failNum; FailNumber = entity.failNum; if(CaseTotalNum == 0){ rate = "0"; }else { rate = df.format((float)entity.successNum/(float)CaseTotalNum*100); } // System.out.println("統計參數字段:版本"+BuildNum+"模塊:"+Module+"用例數:"+CaseTotalNum+"失敗數:"+FailNumber+"通過率:"+rate+"%"); InsertDB.insertStatisticsDB(BuildNum, Module, CaseTotalNum,FailNumber, rate+"%", databaseName,userName,password,connUrl); } System.out.println("場景統計數據插入DB成功"); br.close(); isr.close(); fis.close(); }catch (IOException e) { throw new BuildException("Could not read jmeter resultLog: " + e.getMessage()); } } //測試 public static void main(String[] args) throws MessagingException, UnsupportedEncodingException { DBTask mt = new DBTask(); mt.setResultLog("/InterfaceAutoTestReport.jtl"); mt.execute(); } }
下面是我的命名規范(大家根據自己不同業務不需求進行優化和獲取)

好了,開發到此結束,接下來就是在配置文件中配置jdbc
在target name增加一個insertDB


需要依賴包:mysql-jdbc放到ant的lib目錄下
成果展示:
jenkins持續集成日志:

DB數據展示:
詳情表:

統計表:

