
引言:
有时工作中有事临时走开,如果执行case过程中没有出错,不出意外是不会看日志了,但是如果忘了看执行结果怎么办??总不能重新运行一次,所以今天讲邮件发送,叮~一声,提醒我们看邮箱。
注:依赖环境Allure、JsonPath、testNG;
1.引入pom依赖:
<!-- https://mvnrepository.com/artifact/javax.mail/mail --><dependency><groupId>javax.mail</groupId><artifactId>mail</artifactId><version>1.4.7</version></dependency>
2.封装一个发送邮件的util,代码如下:
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.jayway.jsonpath.DocumentContext;import com.jayway.jsonpath.JsonPath;import org.apache.log4j.Logger;import javax.activation.DataHandler;import javax.activation.DataSource;import javax.activation.FileDataSource;import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import java.io.*;import java.util.*;/*** @author Knife* @description 发送自动化测试报告* @createTime 2020-05-13 21:53*/public class SendEmail extends Rest_Perfect {private static Logger logger = Logger.getLogger(SendEmail.class);private static SendEmail sendEmail;static {}/*** 获取sendEmail对象** @return*/public static SendEmail getInstance() {if (Objects.isNull(sendEmail)) {sendEmail = new SendEmail();}return sendEmail;}/*** 发送邮件** @param title 邮件标题* @param filePath allure-report中suite.json文件路径* @param addresseeEmail 收件邮箱*/public static void send(String title, String filePath, String addresseeEmail) {//根据运行测试类,和main入口判断String p = SendEmail.class.getResource("/").getPath();String[] split = p.split("/");for (String s : split) {if ("test-classes".equals(s)) {filePath = p.substring(0, p.indexOf("/test-classes")) + filePath;}if ("classes".equals(s)) {filePath = p.substring(0, p.indexOf("/classes")) + filePath;}}//获取allure报告内容String sendEmailText = getAllureResult(filePath);// 创建一个Property文件对象Properties props = new Properties();// 设置邮件服务器的信息,这里设置smtp主机名称props.put("mail.smtp.host", "smtp.163.com");// 设置socket factory 的端口props.put("mail.smtp.socketFactory.port", "465");// 设置socket factoryprops.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");// 设置需要身份验证props.put("mail.smtp.auth", "true");// 设置SMTP的端口,QQ的smtp端口是25props.put("mail.smtp.port", "25");// 身份验证实现Session session = Session.getDefaultInstance(props, new Authenticator() {protected PasswordAuthentication getPasswordAuthentication() {// 第二个参数,就是我网易邮箱开启smtp的授权码return new PasswordAuthentication("Kinfe_1114@163.com", "****这里填写自己邮箱和授权码");}});try {// 创建一个MimeMessage类的实例对象Message message = new MimeMessage(session);// 设置发件人邮箱地址message.setFrom(new InternetAddress("Kinfe_1114@163.com"));// 设置收件人邮箱地址message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(addresseeEmail));// 设置邮件主题title = getFormatDateTime() + " " + title;message.setSubject(title);// 创建一个MimeBodyPart的对象,以便添加内容BodyPart messageBodyPart1 = new MimeBodyPart();// 设置邮件正文内容messageBodyPart1.setText(sendEmailText);// 创建另外一个MimeBodyPart对象,以便添加其他内容MimeBodyPart messageBodyPart2 = new MimeBodyPart();// 创建一个datasource对象,并传递文件DataSource source = new FileDataSource(filePath);// 设置handlermessageBodyPart2.setDataHandler(new DataHandler(source));// 加载文件/*messageBodyPart2.setFileName(filePath);*/// 创建一个MimeMultipart类的实例对象Multipart multipart = new MimeMultipart();// 添加正文1内容multipart.addBodyPart(messageBodyPart1);// 添加正文2内容//multipart.addBodyPart(messageBodyPart2);// 设置内容message.setContent(multipart);// 最终发送邮件Transport.send(message);logger.info("\n邮件主题:" + title +"\n邮件内容:" + sendEmailText +"\n收件人邮箱:" + addresseeEmail +"\n****************************邮件发送成功****************************");} catch (MessagingException e) {logger.error("邮件发送异常!");logger.error("报错为:" + e);}}/*** 解析allure-report中suite.json文件内容** @param jsonFilePath* @return*/public static String getAllureResult(String jsonFilePath) {//定义储存用例结果的容器StringBuffer suiteResult = new StringBuffer();int p_sum = 0; //执行成功case总数int f_sum = 0; //执行失败case总数int timeSum = 0; //运行总共花费时间//存储测试方法名Object caseName = null;try (FileInputStream fileInputStream = new FileInputStream(jsonFilePath)) {//获取documentContext对象DocumentContext documentContext = JsonPath.parse(fileInputStream);//操作documentContext读取json文件中的内容List<LinkedHashMap<String, Object>> caseList = documentContext.read("$.children[*].children[*].children[*].children[*]");//遍历获取到的所有测试类HashMap<String, Object> err_Map = new HashMap<>();for (LinkedHashMap<String, Object> linkedHashMap : caseList) {for (Map.Entry<String, Object> entry : linkedHashMap.entrySet()) {//获取测试方法名if ("name".equals(entry.getKey())) {caseName = entry.getValue();}//获取case执行结果状态if ("status".equals(entry.getKey())) {if ("passed".equals(entry.getValue())) {p_sum++;} else if ("failed".equals(entry.getValue())) {//记录是失败caseerr_Map.put("err_Case" + (f_sum + 1), caseName);f_sum++;}}//获取case执行时间if ("time".equals(entry.getKey())) {Map<String, Object> timeMap = JSONObject.parseObject(JSON.toJSONString(entry.getValue()));Integer duration = (Integer) timeMap.get("duration");timeSum += duration;}}}suiteResult.append("\nCase执行总数:" + (p_sum + f_sum));suiteResult.append("\n通过:" + p_sum + "条");suiteResult.append("\n失败:" + f_sum + "条");suiteResult.append((f_sum != 0 ? ("\n执行失败Method:" + err_Map.toString()) : ""));suiteResult.append("\n执行花费时间:" + (timeSum / 1000) + "秒");logger.info("allure-report解析成功");return suiteResult.toString();} catch (Exception e) {logger.error("请检查路径,获取json文件内容!");logger.error("报错内容:" + e);}return null;}}
3.加一个util执行dos,用于初始化删除allure遗留的json文件,以及将allure.json文件通过serve开启服务,转成html文件直接访问,代码如下:
import org.apache.log4j.Logger;
import java.io.*;
/**
* @author Knife
* @description
* @createTime 2020-05-13 15:49
*/
public class OutputDos extends Rest_Perfect {
private static Logger logger = Logger.getLogger(OutputDos.class);
private static String classPath = OutputDos.class.getResource("/").getPath();
static {
//获取target根路径
classPath = classPath.substring(1, classPath.indexOf("test-classes"));
}
/**
* 输入路径(从target根路径输入):删除目录下全部文件
*
* @param path
*/
public static void delAllureResults(String path) {
File file = new File(classPath + path);
File[] files = file.listFiles();
for (File f : files) {
f.delete();
logger.info(String.format("当前文件:%s,删除成功", f));
}
}
/**
* 输入路径(从target根路径输入):results和report得到allure得html报告
*
* @param rawPath
* @param outPath
*/
public static void allureGenerateHtmlReport(String rawPath, String outPath) {
StringBuffer dos = new StringBuffer();
dos.append(String.format("cmd /c allure generate %s -o %s --clean", (classPath + rawPath), (classPath + outPath)));
//如果还有dos命令需要执行,用"&&"表示下一条
//dos.append(String.format("&& allure serve %s",(classPath + rawPath)));
try {
//执行dos命令
Process exec = Runtime.getRuntime().exec(dos.toString());
exec.waitFor();
} catch (Exception e) {
logger.error("文件路径错误,请重新输入!");
logger.error("报错内容:" + e);
}
}
}
4.编写一个class取名BaseTest,代码如下:
import cn.Knife.Wework.Utils.OutputDos;
import cn.Knife.Wework.Utils.SendEmail;
import io.qameta.allure.Description;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import java.util.Objects;
/**
* @author Knife
* @description
* @createTime 2020-05-13 23:03
*/
public class BaseTest {
private static OutputDos od;
private static SendEmail sendEmail = SendEmail.getInstance();
@Description("删除allure遗留的测试结果")
@BeforeSuite
public void be() {
if (Objects.isNull(od)) {
od = new OutputDos();
//运行前删除allure遗留测试结果
od.delAllureResults("/allure-results");
}
}
@Description("解析allure.json文件为report,发送邮件")
@AfterSuite
public void af() {
//解析allure的json文件为html
od.allureGenerateHtmlReport("/allure-results", "/allure-report");
sendEmail.send("接口自动化测试", "/allure-report/data/suites.json", "2538699146@qq.com");
}
}
开始测试,写一段小代码继承BaseTest,如下:
import cn.Knife.Wework.BaseTest;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* @author Knife
* @description
* @createTime 2020-05-15 1:59
*/
public class SendEmailTest extends BaseTest {
@Test
public void test1() {
String s = "我来测试了";
Assert.assertEquals(s,"我来测试了");
}
@Test
public void test2() {
String s = "我来测试了";
Assert.assertEquals(s,"我来测试了");
}
@Test
public void test3() {
String s = "我来测试了";
Assert.assertEquals(s,"我来测试了");
}
@Test
public void test4() {
String s = "我来测试了";
Assert.assertEquals(s,"我来测试了");
}
}
运行结果:
case执行完,邮件马上发送,下面看一下异常case执行会有什么效果,先增加两条异常用例,如下:
@Test
public void errTest() {
Object o = null;
Assert.assertNotNull(o);
}
@Test
public void errTestNotEquals(){
String a = "Knife";
String b = "Knife";
Assert.assertNotEquals(a,b);
}
查看发送的邮件,执行出错的case,会记录下来method,如下:



