jenkins系列:获取jenkins 指定job最新结果并解析日志,整合成测试报告并发送邮件

背景: 

        公司使用jenkins进行环境部署、自动化定时执行完成持续集成流水线,但并不希望每天点开jenkins job去查看执行结果,这样很麻烦,希望对每日集成部署环境得自动化测试结果进行汇总,邮件接收每日整体结果即可,有异常时才会进行详细报告查看。所以我们需要对每日持续集成环境中得自动化结果收集并整合成一份整体报告,并以邮件得形式发送给相关人员。

一、通过jenkinsServer获取最新job日志

        本次实现用到得语言和技术为:  java、 JenkinsServer。 通过JenkinsServer可以获取指定job最后一次构建日志:

a, 首先是连接jenkins,这里使用token, 可绕开403 forbidden的问题

    /**
     * 连接 Jenkins
     */
    public static JenkinsServer connection() {
        JenkinsServer jenkinsServer = null;
        try {
            jenkinsServer = new JenkinsServer(new URI(jenkinsUrl), username,token);   // 使用token, 可绕开403 forbidden的问题
        } catch (URISyntaxException e) {
            e.printStackTrace();
		}
        return jenkinsServer;
    }

备注: jenkins用户得api token需要在jenkins中创建

jenkins系列:获取jenkins 指定job最新结果并解析日志,整合成测试报告并发送邮件_第1张图片

 b, 获取指定job得最新构建日志:

 
	/**
	 * 获取最后一次构建的日志
	 * @param jenkinsServer
	 * @param jobName
	 * @return
	 * @throws Exception
	 */
	public static String getConsoleOutLog(JenkinsServer jenkinsServer, String jobName) throws Exception{
	         JobWithDetails jobWithDetails = jenkinsServer.getJob(jobName).details();
	         ConsoleLog consoleLog = jobWithDetails.getLastBuild().details().getConsoleOutputText(0);  //获取最后一次构建的日志
	         String consoleTxt = consoleLog.getConsoleLog();
	         return consoleTxt;
	    }

二、解析日志

        需要根据日志内容匹配执行结果,主要是用到正则匹配:

     /**
     * 解析日志获取ui自动化执行结果
     * @param log
     * @return
     */
    public String[] analysisUILogResult(String log) {
		String reg = "(Total tests run: )(\\d*, )(Failures: )(\\d*, )(Skips: )(\\d*)";
		Pattern p = Pattern.compile(reg);
		Matcher m = p.matcher(log);
		String logResult = "";
		while(m.find()){
			logResult = m.group();
			System.out.println(logResult);
		}
		String[] temp = logResult.split(",");
		for (int i = 0; i < temp.length; i++) {
			temp[i] = temp[i].split(":")[1].replace(" ", "");
		}
		String[] result = new String[5];
		if (temp.length !=0) {
			result[1] = temp[0];   //总数
			result[3] = temp[1];   //失败
			result[4] = temp[2];   //跳过
			result[2] = String.valueOf(Integer.valueOf(temp[0]) - Integer.valueOf(temp[1]) - Integer.valueOf(temp[2]));   //成功
			result[0] = String.valueOf((double)(Math.round(Integer.valueOf(result[2])*10000/Integer.valueOf(result[1]))/10000.0)*100) + "%";    //通过率
		}
		return result;
	}

三、整合多个job得结果:

        通常会执行接口自动化和ui自动化,需要整合两个job得结果:

    /**
     * 获取整合后的执行结果信息
     * @param jobNames
     * @return
     */
    public HashMap getConsolidateReport(String[] jobNames) {
		JenkinsServer jenkinsServer = connection();
		String log = "";
		String[] resultTemp = new String[5];
		HashMap allResultMap = new HashMap<>();
		if (jobNames.length == 0) {
			jobNames = new String[]{"接口/AutoTest-YC-接口", "AutoTest-Selenium_AutoTest"};
		}
		try {
			for (int i = 0; i < jobNames.length; i++) {
				String[] resultMap = new String[6];   //多一个构建链接
				log = getConsoleOutLog(jenkinsServer, jobNames[i]);
				if (jobNames[i].contains("Selenium")) {
					System.out.println("UI自动化结果为(job名为"+ jobNames[i] +"):\n");
					resultTemp = analysisUILogResult(log);
					System.out.println("【成功率】:" + resultTemp[0] + "\n"+
										"【用例总数】:" + resultTemp[1] + "\n"+
										"【成功】:" + resultTemp[2] + "\n"+
										"【失败】:" + resultTemp[3] + "\n"+
										"【跳过】:" + resultTemp[4] + "\n");
					resultMap[5] = getLastBuildLink(jobNames[i]);
				}else if(jobNames[i].contains("-YC-")) {
					System.out.println("\n云测pub接口自动化结果为(job名为"+ jobNames[i] +"):\n");
					resultTemp = analysisYCLogResult(log);
					System.out.println("【成功率】:" + resultTemp[0] + "\n"+
							"【用例总数】:" + resultTemp[1] + "\n"+
							"【成功】:" + resultTemp[2] + "\n"+
							"【失败】:" + resultTemp[3] + "\n"+
							"【跳过】:" + resultTemp[4] + "\n");
					resultMap[5] = "https://yc.mingyuanyun.com/#/125/org_detail";
				}
				for (int j = 0; j < resultTemp.length; j++) {
					resultMap[j] = resultTemp[j];
				}
				allResultMap.put(jobNames[i], resultMap);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return allResultMap;
	}

四、编辑邮件模板并发送邮件

a, 模板:


自动化测试整合报告
自动化测试整合报告(UI+pub接口)

Hi All,

{1}

{3} {4}

{2}

b, 设置邮件内容:

     /**
     * 设置邮件内容
     * @return
     * @throws IOException
     */
    private String buildContent(String[] jobNames) throws IOException {
        //加载邮件html模板
		String path = System.getProperty("user.dir") + "/conf/pod-scale-alarm.html";
        InputStream inputStream = new FileInputStream(path);;
        BufferedReader fileReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        try {
            while ((line = fileReader.readLine()) != null) {
                buffer.append(line);
            }
        } catch (Exception e) {
//            LOGGER.error("读取文件失败,fileName:{}", fileName, e);
        } finally {
            inputStream.close();
            fileReader.close();
        }


        String contentText = "以下自动化测试整体执行结果(详情点击任务名称查看):
"; //邮件表格header String header = "自动化任务名称成功率用例总数成功失败跳过"; StringBuilder linesBuffer = addResult(jobNames); //蓝色 String emailHeadColor = "#9fc5e8"; String date = DateFormatUtils.format(new Date(), "yyyy/MM/dd HH:mm:ss"); //填充html模板中的五个参数 String htmlText = MessageFormat.format(buffer.toString(), emailHeadColor, contentText, date, header, linesBuffer.toString()); //改变表格样式 htmlText = htmlText.replaceAll("", ""); htmlText = htmlText.replaceAll("", ""); System.out.println(htmlText); return htmlText; } /** * 将jenkins报告结果拼接到html中 * @param jobNames * @return */ public StringBuilder addResult(String[] jobNames) { String jobName = "",key="", value=""; String[] valueList = new String[5]; //获取jenkins整合结果信息 ConsolidateJenkinsReport jenkins = new ConsolidateJenkinsReport("http://10.5.10.154:8085/", "admin", "116a2d55eb2dd1768aec59defe3a8cf4c6"); HashMap resultContent = jenkins.getConsolidateReport(jobNames); // 将jenkins报告结果拼接到html中 StringBuilder linesBuffer = new StringBuilder(); for (Entry entry : resultContent.entrySet()) { jobName = entry.getKey(); valueList = entry.getValue(); linesBuffer.append("" + jobName + ""); //把job名称加入,并添加链接 for (int i = 0; i < valueList.length-2; i++) { //把总体结果信息加入 linesBuffer.append("" + valueList[i] + ""); } linesBuffer.append("" + valueList[4] + ""); //最后一个属性格式单独处理 } return linesBuffer; }

c, 发送邮件:

    /**
	 * 发送html格式的邮件。普通常规方法
	 * @param receiverList
	 * @throws MessagingException
	 * @throws IOException
	 */
	  public void sendEmail(String[] jobNames, InternetAddress[] receiverList, String productVersion) throws MessagingException, IOException {
		  System.err.println(jobNames[0]);
	      Properties props = new Properties();
	      props.setProperty("mail.smtp.host", "smtp.exmail.qq.com");
	      props.setProperty("mail.transport.protocol", "smtp");
	      props.setProperty("mail.smtp.auth", "true");
	      props.setProperty("mail.smtp.connectiontimeout", "20000");
	      props.setProperty("mail.smtp.timeout", "20000");
	      // 得到回话对象
         Session session = Session.getInstance(props);
         // 获取邮件对象
         Message message = new MimeMessage(session);
         // 设置发件人邮箱地址
         message.setFrom(new InternetAddress("[email protected]"));
         // 设置收件人邮箱地址 
         message.setRecipients(Message.RecipientType.TO, receiverList);
         message.setRecipients(Message.RecipientType.CC, receiverList);
//         message.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));//一个收件人
         // 设置邮件标题
         message.setSubject("自动化测试结果报告:" + productVersion);
         
         //邮箱内容以及附件
         Multipart multipart=new MimeMultipart();
         try {
			multipart.addBodyPart(createContent(buildContent(jobNames)));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	     message.setContent(multipart);
	     // 得到邮差对象
	     Transport transport = session.getTransport();
	     // 连接自己的邮箱账户
	     transport.connect("[email protected]", "qCBPfg2FUBYBxCjw");// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码
	     // 发送邮件
	     transport.sendMessage(message, message.getAllRecipients());
	     transport.close();
	  }

d, 邮件效果:

        点击自动化任务名称可跳转至jenkins中该job页面

jenkins系列:获取jenkins 指定job最新结果并解析日志,整合成测试报告并发送邮件_第2张图片

你可能感兴趣的:(Jenkins,jenkins,java,持续集成)