生成的单html方便jenkins集成发邮件,= = 构建失败发邮件
参考:https://blog.csdn.net/galen2016/article/details/77975965
步骤:
1.安装Email Extension Plugin插件
2.系统管理--系统设置
--设置jenkins Location的邮箱,这里是管理员邮箱,要和发件人的邮箱设置为同一个
--设置email extension plugin
--设置邮件通知,可以测试一下收发件
2.进入项目-设置-构建后操作
--高级设置
--Default Content内容
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<div>
<table width="95%" cellpadding="0" cellspacing="0"
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<th align="center" colspan="2"><br />
<h2>构建信息</h2>
</th>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li><br />
<li>详细测试报告 : <a href="${PROJECT_URL}测试报告">${PROJECT_URL}测试报告</a></li><br />
<li>触发原因: ${CAUSE}</li><br />
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li><br />
</ul>
</td>
<td>${JELLY_SCRIPT,template="html"}<br/>
</tr>
<tr>
<td colspan="2" align="center"><br />
<h2>测试报告</h2>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<div>${FILE ,path="C:/Users/user/workspace/testngDemo/test-output/emailable-report.html"}</div>
</td>
</tr>
</table>
</div>
</body>
</html>
失败重跑 testng实现 √
https://blog.csdn.net/u011541946/article/details/78688302
有两种实现方法:
1.用runtestng直接java执行
2.用testng的监听
Retry设定重跑次数
public class Retry implements IRetryAnalyzer {
private int retryCount =0;
private int maxRetryCount =2;
@Override
public boolean retry(ITestResult result){
if(retryCount<maxRetryCount){
retryCount++;
return true;
}
return false;
}
}
重跑的监听器
public class RetryTestListener implements IAnnotationTransformer {
public void transform(ITestAnnotation annotation, Class testClass,
Constructor testConstructor, Method testMethod) {
IRetryAnalyzer retry = annotation.getRetryAnalyzer();
if (retry == null) {
annotation.setRetryAnalyzer(Retry.class);
}
}
}
设置用例结束的监听器
public class ListenerTest extends TestListenerAdapter{
@Override
public void onFinish(ITestContext testContext){
super.onFinish(testContext);
Iterator<ITestResult> listOfFailedTests=testContext.getFailedTests().getAllResults().iterator();
while(listOfFailedTests.hasNext()){
ITestResult failedTest = listOfFailedTests.next();
ITestNGMethod method = failedTest.getMethod();
if(testContext.getFailedTests().getResults(method).size()>1){
listOfFailedTests.remove();
}else{
if(testContext.getPassedTests().getResults(method).size()>0){
listOfFailedTests.remove();
}
}
}
}
}
在testng.xml中配置监听器
<listeners >
<listener class-name="b.testng.reportRelated.ListenerTest"/>
<listener class-name="com.test.RetryTestListener"/>
</listeners>
失败用例截图√
截图方法:
public class ScreenScr {
public static void getScreen(TakesScreenshot driver ,String picName){
String filePath=System.getProperty("user.dir");
File pic=driver.getScreenshotAs(OutputType.FILE);
// String picName=System.currentTimeMillis()+".png";
try {
FileUtils.copyFile(pic, new File(filePath+"\\pic\\"+picName+".png"));
} catch (IOException e) {
e.printStackTrace();
}finally{
Reporter.log("GetScreenshot Successful"+filePath+"\\pic\\"+picName);
}
}
}
失败和截图结合起来,把截图方法放进TestListenerAdapter的继承类里面。
public class ListenerTest extends TestListenerAdapter{
private Logger logger = Logger.getLogger(ListenerTest.class);
private int m_count = 0;
String filePath=System.getProperty("user.dir");
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
String picName =tr.getStartMillis()+"";
ScreenScr.getScreen(PhoneDriver.getPhoneDriver(), picName);
log("["+tr.getName()+" Failure ]"+"F");
Reporter.log("["+tr.getName()+"失败]");
}
@Override
public void onTestSkipped(ITestResult tr) {
super.onTestSkipped(tr);
String picName =tr.getStartMillis()+"";
ScreenScr.getScreen(PhoneDriver.getPhoneDriver(), picName);
log("["+tr.getName()+" skipped ]"+"S");
Reporter.log("["+tr.getName()+"跳过]");
}
}
最后一步,把失败截图放进报告,这里我用的extentReporter,继承了IReporter
这里截取一段用到截图的代码,是extentReporter在报告中,对用例结果的显示的代码,其他项目可以参考。
if (result.getThrowable() != null) {
try {
String fileName=System.getProperty("user.dir")+"\\pic\\"+result.getStartMillis()+".png";
test.addScreenCaptureFromPath(fileName);//本地可看,klov端裂图,klov的bug
//本地和klov都可看
test.fail("截图", MediaEntityBuilder.createScreenCaptureFromPath(fileName).build());
} catch (IOException e) {
e.printStackTrace();
}
test.log(status, result.getThrowable());
}else {
test.log(status, "Test " + status.toString().toLowerCase() + "ed");
}
用例执行失败发测试报告邮件
参考:https://www.cnblogs.com/h--d/p/6138900.html
https://www.cnblogs.com/ysocean/p/7666061.html
步骤
1.写一个发邮件的类Mail,这里把测试报告的html放在附件里面发送了。也可以放在content里面。
package b.testng.reportRelated;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
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 Email {
// supply your SMTP host name
private static String host = "smtp.163.com";
// supply a static sendTo list
private static String to = "350xxxxx@qq.com";
// supply the sender email
private static String from = "yxxxxx@163.com";
private static String password = "Yxxxxxx";
/*
* // default cc list 抄送 private static String cc = ""; // default bcc list
* 密送 private static String bcc = "";
*/
private static String htmlToContents(String htmlPath, String htmlName) {
String string = "";
FileReader in;
try {
in = new FileReader(htmlPath + htmlName);
char[] buff = new char[1024 * 10];
in.read(buff);
string = new String(buff);
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return string;
}
private static void sendEmail(String from, String to, String subject, String content, String htmlPath,
String htmlName,String attachPath, String attachName) {
try {
// 创建参数配置,用于连接邮件服务器
Properties prop = System.getProperties();
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.host", host);
prop.setProperty("mail.smtp.auth", "true");
// 创建会话,和邮件服务器交互
Session session = Session.getDefaultInstance(prop);
session.setDebug(true);
// 创建一封邮件,设置session,发送者,接收者,标题
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setSubject(subject);
List<String> toList = getAddress(to);
for (String address : toList) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(address));
}
String contents="";
if (!htmlPath.equals("")) {
contents =htmlToContents(htmlPath, htmlName);
}
contents=content+contents;
if (!attachPath.equals("")) {
// 整封邮件的MIME消息体
MimeMultipart msgMultipart = new MimeMultipart("mixed");
// ↑有附件,没有附件会报空指针
message.setContent(msgMultipart);
// 往MIME消息体中,加入附件
MimeBodyPart attch = new MimeBodyPart();
msgMultipart.addBodyPart(attch);
// 把文件添加到attch中
// 设置数据源
DataSource ds = new FileDataSource(new File(attachPath + attachName));
// 设置数据处理器
DataHandler dHandler = new DataHandler(ds);
// 设置第一个附件的数据
attch.setDataHandler(dHandler);
// 设置第一个附件的文件名
attch.setFileName(attachName);
// 正文
// 往MIME消息体中,加入文字
MimeBodyPart text = new MimeBodyPart();
text.setContent(contents, "text/html;charset=UTF-8");
message.saveChanges();
}
else {
message.setContent(contents, "text/html;charset=UTF-8");
}
// 根据session获取邮件传输对象
Transport transport = session.getTransport();
transport.connect(from, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
/**
* send 2个参数 使用默认邮箱,发送subject和content
*/
public static void send(String subject, String contents) {
sendEmail(from, to, subject, contents, "", "", "", "");
}
/**
* send 3个参数 发送 指定邮箱,不发到默认邮箱,subject和content
*/
public static void send(String to, String subject, String contents) {
sendEmail(from, to, subject, contents, "", "", "", "");
}
/**
* sendAttach 4个参数 使用默认邮箱,发送subject和content,attch
*/
public static void sendAttach(String subject, String contents, String attachPath, String attachName) {
sendEmail(from, to, subject, contents, "", "", attachPath, attachName);
}
/**
* sendAttach 3个参数 使用默认邮箱,发送subject和content,attch
*/
public static void sendAttach(String to, String subject, String contents, String attachPath, String attachName) {
sendEmail(from, to, subject, contents, "", "", attachPath, attachName);
}
private void sendWithPic(String picPath,String picName,String picURL) throws AddressException, MessagingException{
Properties prop = System.getProperties();
prop.setProperty("mail.transport.protocol", "smtp");
prop.setProperty("mail.smtp.host", host);
prop.setProperty("mail.smtp.auth", "true");
// 创建会话,和邮件服务器交互
Session session = Session.getDefaultInstance(prop);
session.setDebug(true);
// 创建一封邮件,设置session,发送者,接收者,标题
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setSubject("subject");
List<String> toList = getAddress(to);
for (String address : toList) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(address));
}
// 5. 创建图片"节点"
MimeBodyPart image = new MimeBodyPart();
// 读取本地文件
DataHandler dh = new DataHandler(new FileDataSource(picPath+picName));
// 将图片数据添加到"节点"
image.setDataHandler(dh);
// 为"节点"设置一个唯一编号(在文本"节点"将引用该ID)
image.setContentID(picName);
// 6. 创建文本"节点"
MimeBodyPart text = new MimeBodyPart();
// 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片
text.setContent("这是一张图片<br/><a href='"+picURL+"'><img src='cid:"+picName+"'/></a>", "text/html;charset=UTF-8");
// 7. (文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点")
MimeMultipart mm_text_image = new MimeMultipart();
mm_text_image.addBodyPart(text);
mm_text_image.addBodyPart(image);
mm_text_image.setSubType("related"); // 关联关系
// 8. 将 文本+图片 的混合"节点"封装成一个普通"节点"
// 最终添加到邮件的 Content 是由多个 BodyPart 组成的 Multipart, 所以我们需要的是 BodyPart,
// 上面的 mailTestPic 并非 BodyPart, 所有要把 mm_text_image 封装成一个 BodyPart
MimeBodyPart text_image = new MimeBodyPart();
text_image.setContent(mm_text_image);
//设置邮件的发送时间,默认立即发送
message.setSentDate(new Date());
}
/**
* 发送标题,内容,html
*
* @param subject
* @param contents
* @param htmlPath
* @param htmlName
*/
public static void sendHtml(String subject, String contents, String htmlPath, String htmlName) {
sendEmail(from, to, subject, contents, htmlPath, htmlName, "", "");
}
/**
* 发送标题,html
*
* @param subject
* @param htmlPath
* @param htmlName
*/
public static void sendHtml(String subject, String htmlPath, String htmlName) {
sendEmail(from, to, subject, "", htmlPath, htmlName, "", "");
}
private static List<String> getAddress(String address) {
List<String> addressList = new ArrayList<String>();
if (address.isEmpty())
return addressList;
if (address.indexOf(";") > 0) {
String[] addresses = address.split(";");
for (String a : addresses) {
addressList.add(a);
}
} else {
addressList.add(address);
}
return addressList;
}
}
2.在maven配置中,增加一个插件,该插件可以在测试失败后执行配置的class的main方法
参考https://blog.csdn.net/qq744746842/article/details/51497506
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>b.testng.reportRelated.Email</mainClass>
<arguments>
<argument>11</argument>
<argument>22</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
package b.testng.reportRelated;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
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 Email {
// supply your SMTP host name
private static String host = "smtp.163.com";
// supply a static sendTo list
private static String to = "350343***@qq.com";
// supply the sender email
private static String from = "yindongzi@163.com";
private static String password = "Yzz1990";
/*
* * // default cc list 抄送 private static String cc = ""; // default bcc
* list * 密送 private static String bcc = "";
*/
private static String htmlToContents(String htmlPath, String htmlName) {
String string = "";
FileReader in;
try {
in = new FileReader(htmlPath + htmlName);
char[] buff = new char[1024 * 10];
in.read(buff);
string = new String(buff);
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return string;
}
private static void sendEmail(String from, String to, String subject, String content, String htmlPath,String htmlName,String attachPath, String attachName) {try {// 创建参数配置,用于连接邮件服务器Properties prop = System.getProperties();prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.host", host);prop.setProperty("mail.smtp.auth", "true");// 创建会话,和邮件服务器交互Session session = Session.getDefaultInstance(prop);session.setDebug(true);// 创建一封邮件,设置session,发送者,接收者,标题MimeMessage message = new MimeMessage(session);message.setFrom(new InternetAddress(from));message.setSubject(subject);List<String> toList = getAddress(to);for (String address : toList) {message.addRecipient(Message.RecipientType.TO, new InternetAddress(address));}String contents="";if (!htmlPath.equals("")) {contents =htmlToContents(htmlPath, htmlName);}contents=content+contents;if (!attachPath.equals("")) {// 整封邮件的MIME消息体MimeMultipart msgMultipart = new MimeMultipart("mixed");// ↑有附件,没有附件会报空指针message.setContent(msgMultipart);// 往MIME消息体中,加入附件MimeBodyPart attch = new MimeBodyPart();msgMultipart.addBodyPart(attch);// 把文件添加到attch中// 设置数据源DataSource ds = new FileDataSource(new File(attachPath + attachName));// 设置数据处理器DataHandler dHandler = new DataHandler(ds);// 设置第一个附件的数据attch.setDataHandler(dHandler);// 设置第一个附件的文件名attch.setFileName(attachName);// 正文// 往MIME消息体中,加入文字MimeBodyPart text = new MimeBodyPart();text.setContent(contents, "text/html;charset=UTF-8");message.saveChanges();}else {message.setContent(contents, "text/html;charset=UTF-8");}// 根据session获取邮件传输对象Transport transport = session.getTransport();transport.connect(from, password);transport.sendMessage(message, message.getAllRecipients());transport.close();} catch (MessagingException e) {e.printStackTrace();}}
/** * send 2个参数 使用默认邮箱,发送subject和content */
public static void send(String subject, String contents) {
sendEmail(from, to, subject, contents, "", "", "", "");
}
/** * send 3个参数 发送 指定邮箱,不发到默认邮箱,subject和content */
public static void send(String to, String subject, String contents) {
sendEmail(from, to, subject, contents, "", "", "", "");
}
/** * sendAttach 4个参数 使用默认邮箱,发送subject和content,attch */
public static void sendAttach(String subject, String contents, String attachPath, String attachName) {
sendEmail(from, to, subject, contents, "", "", attachPath, attachName);
}
/** * sendAttach 3个参数 使用默认邮箱,发送subject和content,attch */
public static void sendAttach(String to, String subject, String contents, String attachPath, String attachName) {
sendEmail(from, to, subject, contents, "", "", attachPath, attachName);
}
private void sendWithPic(String picPath,String picName,String picURL) throws AddressException, MessagingException{Properties prop = System.getProperties();prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.host", host);prop.setProperty("mail.smtp.auth", "true");// 创建会话,和邮件服务器交互Session session = Session.getDefaultInstance(prop);session.setDebug(true);// 创建一封邮件,设置session,发送者,接收者,标题MimeMessage message = new MimeMessage(session);message.setFrom(new InternetAddress(from));message.setSubject("subject");List<String> toList = getAddress(to);for (String address : toList) {message.addRecipient(Message.RecipientType.TO, new InternetAddress(address));} // 5. 创建图片"节点" MimeBodyPart image = new MimeBodyPart(); // 读取本地文件 DataHandler dh = new DataHandler(new FileDataSource(picPath+picName)); // 将图片数据添加到"节点" image.setDataHandler(dh); // 为"节点"设置一个唯一编号(在文本"节点"将引用该ID) image.setContentID(picName); // 6. 创建文本"节点" MimeBodyPart text = new MimeBodyPart(); // 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片 text.setContent("这是一张图片<br/><a href='"+picURL+"'><img src='cid:"+picName+"'/></a>", "text/html;charset=UTF-8"); // 7. (文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点") MimeMultipart mm_text_image = new MimeMultipart(); mm_text_image.addBodyPart(text); mm_text_image.addBodyPart(image); mm_text_image.setSubType("related"); // 关联关系
// 8. 将 文本+图片 的混合"节点"封装成一个普通"节点" // 最终添加到邮件的 Content 是由多个 BodyPart 组成的 Multipart, 所以我们需要的是 BodyPart, // 上面的 mailTestPic 并非 BodyPart, 所有要把 mm_text_image 封装成一个 BodyPart MimeBodyPart text_image = new MimeBodyPart(); text_image.setContent(mm_text_image); //设置邮件的发送时间,默认立即发送 message.setSentDate(new Date());}
/**
* * 发送标题,内容,html * * @param subject * @param contents * @param htmlPath
* * @param htmlName
*/
public static void sendHtml(String subject, String contents, String htmlPath, String htmlName) {
sendEmail(from, to, subject, contents, htmlPath, htmlName, "", "");
}
/** * 发送标题,html * * @param subject * @param htmlPath * @param htmlName */
public static void sendHtml(String subject, String htmlPath, String htmlName) {
sendEmail(from, to, subject, "", htmlPath, htmlName, "", "");
}
private static List<String> getAddress(String address) {
List<String> addressList = new ArrayList<String>();
if (address.isEmpty())
return addressList;
if (address.indexOf(";") > 0) {
String[] addresses = address.split(";");
for (String a : addresses) {
addressList.add(a);
}
} else {
addressList.add(address);
}
return addressList;
}
}