ant+jmeter+jenkins 发送测试报告邮件
Posted timezhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ant+jmeter+jenkins 发送测试报告邮件相关的知识,希望对你有一定的参考价值。
二、部署配置
2.1 jmeter
2.1.1 jar包二次开发:
将jmeter目录D:apache-jmeter-5.0extras中的ant-jmeter-1.1.1.jar包进行反编译。添加2个测试类 MailTask和JavaMail。具体代码参考文件中的java文件。然后进行编译生成新的jar包ant-jmeter-1.1.2-SNAPSHOT.jar。
2.1.2 添加build文件和测试文件
在jmeter目录D:apache-jmeter-5.0 est下新增文件build.xml。
将需要测试的.jmx文件复制到目录D:apache-jmeter-5.0 est。(与build.xml文件同目录)
2.1.3新增测试报告存储目录
在D:apache-jmeter-5.0 est目录下新增文件目录report/jtl和report/html。这2个目录会存储测试执行后的报告文件。
2.2 ant
2.2.1 添加依赖jar包
在目录D:apache-ant-1.10.5lib下添加依赖jar包。javax.mail-1.5.5.jar,activation-1.1.1.jar,mail-2017.10.2.jar,ant-jmeter-1.1.2-SNAPSHOT.jar。
Jar包可以在二次开发时下载找到。
2.3 jenkins
2.3.1 下载war包部署至tomcat
下载jenkins包,直接在tomcat部署。点击start.sh 执行。详情请百度。
JavaMail
package org.programmerplanet.ant.taskdefs.jmeter; import java.io.File; import java.io.UnsupportedEncodingException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.Address; import javax.mail.Authenticator; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimeUtility; public class JavaMail { static File mailAttachmentFile; static public void sendMail(int all, int successnum, int failnum, String htmlstring, String mailSubject, String mailAttachment, String mailAddress, String mailAddressCC, String mailHost, String mailProtocol, String mailHostPort, String mailAddressFrom, String mailAddressFromPwd,String jmeterProjectName,String testCaseStartTime) throws MessagingException, UnsupportedEncodingException { String s; String passStatus;//判定测试状态,测试通过,还是测试失败 String failnumFormat = "";//处理失败数为0时,不要红色显示,失败数大于0时才显示 DecimalFormat df = new DecimalFormat("0.00"); String testCaseEndTime = ""; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (all == 0) { s = "0"; passStatus="无用例被执行"; } else { s = df.format((float) successnum / (float) all * 100); if(failnum>0){ passStatus = "<font color=red>Fail</font>"; failnumFormat = "<font color=red>" + failnum + "</font>"; }else { passStatus = "<font color=green>Pass</font>"; failnumFormat = failnum + ""; } //用例结束时间标注为发邮件时间 testCaseEndTime = simpleDateFormat.format(new Date()); } Properties props = new Properties(); // 开启debug调试 // props.setProperty("mail.debug", "true"); // 发送服务器需要身份验证 props.setProperty("mail.smtp.auth", "flase"); // 设置邮件服务器主机名(ip或者域名) props.setProperty("mail.smtp.host", mailHost); // 发送邮件协议名称 props.setProperty("mail.transport.protocol", mailProtocol); // 发送邮件协议端口 props.setProperty("mail.smtp.port", mailHostPort); //props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // props.setProperty("mail.smtp.ssl.enable", "true");//保证使用ssl时可以发送成功 //props.setProperty("mail.smtp.socketFactory.port", "465"); //props.setProperty("mail.smtp.socketFactory.fallback", "false"); // 设置环境信息 Session session = Session.getDefaultInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(mailAddressFrom, mailAddressFromPwd); } }); // 创建邮件对象 Message msg = new MimeMessage(session); // 设置发件人 msg.setFrom(new InternetAddress(mailAddressFrom)); // 设置收件人 @SuppressWarnings("static-access") Address[] addresses = new InternetAddress().parse(mailAddress); @SuppressWarnings("static-access") Address[] addressesCC = new InternetAddress().parse(mailAddressCC); msg.setRecipients(Message.RecipientType.TO, addresses);// 直送对象 msg.setRecipients(Message.RecipientType.CC, addressesCC);// 抄送对象 // 设置主题 if (mailSubject != null) { if(passStatus.equals("<font color=red>Fail</font>")){ msg.setSubject("【自动化结果通知--Failure】:" + jmeterProjectName); }else if(passStatus.equals("<font color=green>Pass</font>")){ msg.setSubject("【自动化结果通知--Successful】:" + jmeterProjectName); } } else { msg.setSubject("接口测试报告"); } // 设置邮件内容 BodyPart bp = new MimeBodyPart(); Multipart mp = new MimeMultipart(); bp.setContent( "<!DOCTYPE html>" + "<html><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8">" + "<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />" + "<title>JMeter Test Results</title>" + "<style type="text/css">" + "body {background: #ffffff;margin: 0 auto;padding: 0;text-align: left;font-size: 12px;font-family: "微软雅黑", "宋体";}" + "table {font-size: 12px;font-family: "微软雅黑", "宋体";}" + "td {line-height: 20px;}" + "</style></head><body>" + "<table width="800" border="0" cellspacing="0" align="center" cellpadding="0" style="border: #ccc 1px solid;">" + "<tbody><tr><td>" + "<table width="800" border="0" cellpadding="0" cellspacing="0" bgcolor="#fbfbfb" style="border-bottom: #eeeeee 1px solid;border-top: #cc0000 1px solid;">" + "<tbody><tr><td width="100"><img src="http://www.uml.org.cn/jmshj/images/20131211411.jpg" alt="测试结果" width="100" height="40"></td>" + "<td width="264" align="right" style="font-size: 12px; font-weight: bold; color: #999999;padding-top: 5px;"><font color="#136ec2" style="font-size:large">Hi All <br></font>此信为系统邮件,请不要直接回复。</td></tr></tbody></table>" + "<table width="750" border="0" align="center" cellspacing="0" cellpadding="0" style="margin: 28px 28px 10px 28px;">" + "<tbody><tr><td style="font-size: 16px; color: #666666; padding-bottom: 6px;" align="center"><h2>接口测试报告</h2></td></tr></tbody></table>" + "<table width="750" border="0" cellspacing="0" cellpadding="0" align="center"><tbody><tr><td>" + "<table width="750" border="0" align="center" class="table_c" style="border-collapse:collapse;"><tbody><tr>" + "<th width="100" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">测试项目</th>" + "<th width="70" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">测试状态</th>" + "<th width="70" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">用例总数</th>" + "<th width="70" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">成功</th>" + "<th width="70" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">失败</th>" + "<th width="70" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">通过率</th>" + "<th width="100" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">开始时间</th>" + "<th width="100" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">结束时间</th></tr>" + "<tr><td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + jmeterProjectName + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + passStatus + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + all + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + successnum + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + failnumFormat + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + s + "%</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + testCaseStartTime + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + testCaseEndTime + "</td></tr></tbody></table></td></tr></tbody></table></td></tr>" + "<tr><td style="font-size: 12px; line-height: 20px; color: #999999; padding-top:15px; padding-left:25px ">备注:测试报告详细内容见邮件附件。</td></tr><tr><td>" + "<table width="750" border="0" align="center" cellspacing="0" cellpadding="0" style="margin: 28px 28px 10px 28px;">" + "<tbody><tr><td style="font-size: 12px; color: #666666; padding-bottom: 6px;"><strong style="color:red">失败用例:</strong></td></tr></tbody></table>" + "<table width="750" border="0" cellspacing="0" cellpadding="0" align="center"><tbody>" + htmlstring //失败的用例,如无用例失败,则显示无 + "</tbody></table>" + "<table width="750" border="0" align="center" cellspacing="0" cellpadding="0" style="margin: 28px 28px 10px 28px;">" + "<tbody><tr><td style="font-size: 12px; line-height: 20px; color: #999999; padding-top: 6px;">如果您对本次邮件有任何疑问,请联系测试小组人员,感谢您的查阅!</td></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table></body></html>", "text/html;charset=utf-8"); mp.addBodyPart(bp); // 附件为空时不发附件 // mailAttachmentFile = new // File(System.getProperty("user.dir")+mailAttachment); mailAttachmentFile = new File(mailAttachment); if (mailAttachmentFile.exists()) { System.out.println("把mailAttachment报告文件作为附件发送"); bp = new MimeBodyPart(); // FileDataSource fileds = new // FileDataSource(System.getProperty("user.dir")+mailAttachment); FileDataSource fileds = new FileDataSource(mailAttachment); bp.setDataHandler(new DataHandler(fileds)); bp.setFileName(MimeUtility.encodeText(fileds.getName(), "UTF-8", "B")); mp.addBodyPart(bp); } else { System.out.println("mailAttachment文件不存在,邮件添加附件失败,请检查!"); } msg.setContent(mp); msg.saveChanges(); Transport transport = session.getTransport(); // 连接邮件服务器 transport.connect(); // 发送邮件 Transport.send(msg); // 关闭连接 transport.close(); } }
build文件
<?xml version="1.0" encoding="GB2312"?> <project name="ant-jmeter-test" default="run" basedir="."> <!--自动触发测试成功456--> <tstamp> <format property="time" pattern="yyyyMMddHHmmss" /> </tstamp> <property environment="env"/> <!-- 需要改成自己本地的 Jmeter 目录--> <property name="jmeter.home" value="D:apache-jmeter-5.0" /> <!-- jmeter生成jtl格式的结果报告的路径--> <!--<property name="jmeter.result.jtl.dir" value="D:apache-jmeter-3.1demo eportjtl" />--> <!-- jmeter生成html格式的结果报告的路径--> <!--<property name="jmeter.result.html.dir" value="D:apache-jmeter-3.1demo eporthtml" />--> <!-- jmeter生成jtl、html格式的结果报告的路径--> <property name="jmeter.result.jtl.dir" value="D:apache-jmeter-5.0 est eportjtl" /> <property name="jmeter.result.html.dir" value="D:apache-jmeter-5.0 est eporthtml" /> <!-- 生成的报告的前缀--> <property name="ReportName" value="TestReport" /> <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}${time}.jtl" /> <property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}${time}.html" /> <!-- GIT拉取到本地目录路径 <property name="githome" value="${env.WORKSPACE}/接口自动化测试/接口测试" />--> <target name="run"> <echo message="start..."/> <!--<antcall target="clean" />--> <antcall target="test" /> <antcall target="report" /> <antcall target="mail" /> </target> <!-- <target name="clean"> <mkdir dir="${env.WORKSPACE}/results/${env.BUILD_ID}" /> </target> --> <target name="test"> <taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" /> <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}"> <!-- 声明要运行的脚本。"*.jmx"指包含此目录下的所有jmeter脚本--> <testplans dir="D:apache-jmeter-5.0 est" includes="*.jmx" /> <property name="jmeter.save.saveservice.output_format" value="xml"/> </jmeter> </target> <path id="xslt.classpath"> <fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/> <fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/> </path> <target name="report"> <tstamp><format property="report.datestamp" pattern="yyyy/MM/dd HH:mm"/></tstamp> <xslt classpathref="xslt.classpath" force="true" in="${jmeter.result.jtlName}" out="${jmeter.result.htmlName}" style="${jmeter.home}/extras/jmeter-results-detail-report_30.xsl"> <param name="dateReport" expression="${report.datestamp}"/> </xslt> <!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 --> <copy todir="${jmeter.result.html.dir}"> <fileset dir="${jmeter.home}/extras"> <include name="collapse.png" /> <include name="expand.png" /> </fileset> </copy> </target> <target name="mail"> <taskdef name="javamail" classname="org.programmerplanet.ant.taskdefs.jmeter.MailTask"/> <javamail resultLog="${jmeter.result.jtlName}" mailAddressFrom="" mailAddressFromPwd="" jmeterProjectName="XXX项目接口测试" mailAddress="[email protected]" mailAddressCC="[email protected]" mailHost="" mailProtocol="smtp" mailHostPort="" mailSubject="${ReportName}${time}" mailAttachment="${jmeter.result.htmlName}"> </javamail> <!-- mailAddressFrom:发件人邮箱 mailAddressFromPwd:发件人邮箱密码 jmeterProjectName:本脚本主题是什么 mailAddress:收件人邮箱,多个邮箱间逗号隔开 mailAddressCC:抄送件人邮箱,多个邮箱间逗号隔开 mailHost:发件人邮箱服务器地址 mailProtocol:邮箱服务器协议 mailHostPort:邮箱服务器端口 resultLog:jtl文件,不需要修改 mailSubject:html文件,不需要修改 mailAttachment:附件,不需要修改 --> <echo>发送报告邮件 at ${time}</echo> </target> </project>
MailTask 类
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.SimpleDateFormat; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; public class MailTask extends Task { private String mailAddress = null;// 主送邮件对象地址 private String mailAddressCC = null;// 抄送邮件对象地址 private String mailSubject = null;// 邮件主题 private String mailAttachment = null;// 邮件附件 private String mailHost = null;// 邮件服务器 private String mailProtocol = null;// 发送邮件协议 private String mailHostPort = null;// 发送邮件协议的端口 private String mailAddressFrom = null;// 发件人 private String mailAddressFromPwd = null;// 发件人密码,是授权码 private String jmeterProjectName = null;// jmeter脚本名字 private String resultLog = null; File resultLogFile; File htmlFile; // jtl文件 public void setResultLog(String resultLog) { this.resultLog = resultLog; } public String getResultLog() { return resultLog; } // 邮件主题 public void setMailSubject(String mailSubject) { this.mailSubject = mailSubject; } public String getMailSubject() { return mailSubject; } // 附件 html报告文件 public void setMailAttachment(String mailAttachment) { this.mailAttachment = mailAttachment; } public String getMailAttachment() { return mailAttachment; } // 收件地址,多个逗号(英文)隔开 public void setMailAddress(String mailAddress) { this.mailAddress = mailAddress; } public String getMailAddress() { return mailAddress; } // 抄送邮件地址,多个逗号(英文)隔开 public void setMailAddressCC(String mailAddressCC) { this.mailAddressCC = mailAddressCC; } public String getMailAddressCC() { return mailAddressCC; } public void setMailHost(String mailHost) { this.mailHost = mailHost; } public String getMailHost() { return mailHost; } public void setMailProtocol(String mailProtocol) { this.mailProtocol = mailProtocol; } public String getMailProtocol() { return mailProtocol; } public void setMailAddressFrom(String mailAddressFrom) { this.mailAddressFrom = mailAddressFrom; } public String getMailAddressFrom() { return mailAddressFrom; } public void setMailAddressFromPwd(String mailAddressFromPwd) { this.mailAddressFromPwd = mailAddressFromPwd; } public String getMailAddressFromPwd() { return mailAddressFromPwd; } public void setMailHostPort(String mailHostPort) { this.mailHostPort = mailHostPort; } public String getMailHostPort() { return mailHostPort; } public void setJmeterProjectName(String jmeterProjectName) { this.jmeterProjectName = jmeterProjectName; } public String getJmeterProjectName() { return jmeterProjectName; } /** * @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); resultLogFile = new File(resultLog); if (mailAddress != null && resultLogFile.exists()) { System.out.println("开始解析resultLog"); try { analyseResultLog(); } catch (MessagingException e) { e.printStackTrace(); } } else { System.out.println("resultLog不存在,请检查!"); } } /** * 计算统计数据 * * @throws MessagingException */ private void analyseResultLog() throws BuildException, MessagingException { /* * String htmlString = "<tr valign="top">" + * "<th width="50%">接口</th>" + "<th>执行结果</th>" + "<th>执行时间</th>" + * "</tr>"; */ String htmlString = "<tr><th width="250" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">接口</th>" + "<th width="65" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">执行结果</th>" + "<th width="65" height="28" align="center" bgcolor="#FFFFFF" style="border:1px solid #ccc;">执行时间</th></tr>"; String time; String name; int count = 0;// 总用例数量 String color; String color1 = "#FFFFFF";// 白色 String color2 = "#FF0000";// 红色 int successnum = 0;// 成功用例数量 int failnum = 0;// 失败用例数量 String testCaseStartTime = ""; SimpleDateFormat simpleDateFormat = null; try { // FileInputStream fis = new // FileInputStream(System.getProperty("user.dir") + resultLog); FileInputStream fis = new FileInputStream(resultLog); InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { if (line.indexOf("<httpSample ") != -1) { count = count + 1;// 统计用例个数 simpleDateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); // 获取用例开始时间 if(count==1){ String startTimeMilTime = line.split(""")[9]; testCaseStartTime = simpleDateFormat.format(Long .parseLong(startTimeMilTime)); } if (line.indexOf(" s="true"") != -1) { successnum = successnum + 1; color = color1; time = line.split(""")[1]; name = line.split(""")[13]; //不显示成功的用例 /*htmlString = htmlString + "<tr><td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + name + "</td>" + "<td height="28" bgcolor="" + color + "" align="center" style="border:1px solid #ccc;">成功</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + time + "ms</td></tr>";*/ } else { failnum = failnum + 1; color = color2; time = line.split(""")[1]; name = line.split(""")[13]; htmlString = htmlString + "<tr><td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + name + "</td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;"><font color=" + color + ">失败</font></td>" + "<td height="28" bgcolor="#FFFFFF" align="center" style="border:1px solid #ccc;">" + time + "ms</td></tr>"; } } } // 无失败用例的时候,直接显示无即可 if (failnum <= 0) { htmlString = "<tr><td> ~~~太棒啦,没有失败的用例哦 ^_^</td></tr>"; } if (successnum + failnum > 0) { // 有http请求才发邮件 JavaMail.sendMail(successnum + failnum, successnum, failnum, htmlString, mailSubject, mailAttachment, mailAddress, mailAddressCC, mailHost, mailProtocol, mailHostPort, mailAddressFrom, mailAddressFromPwd, jmeterProjectName, testCaseStartTime); System.out.println("邮件发送成功"); } br.close(); isr.close(); fis.close(); } catch (IOException e) { throw new BuildException("Could not read jmeter resultLog: " + e.getMessage()); } } }