RobotFramework与Jenkins集成发送邮件
转:
A. 目标:
实现RobotFramework的脚本定时自动执行,执行完后自动将结果发送到指定邮箱
B. 前提
1、 配置好Robot Framework的环境,脚本可以正常运行
2、 部署好Jenkins的环境,Jenkins的安装不是本文的重点,不懂的请问度娘(其实很简单,装Tomcat,把Jenkins.war包扔到Tomcat的webapp目录里)
3、 在Jenkins里安装好以下插件:EmailExtension Plugin、Zentimestamp plugin、Robot Framework plugin
C. 安装相关插件
Jenkins安装Email Extension Plugin、Zentimestampplugin、Robot Framework plugin插件
在线直接安装插件:
在“可选插件”搜索Email Extension Plugin、Zentimestamp plugin、Robot Frameworkplugin插件名,选择之后,点击直接安装
注:建议用在线直接安装,因为插件与插件中存在相互依赖性,手动处理会很麻烦,但是直接安装,系统可以直接处理依赖关系
离线安装插件:(不建议使用)
1) 下载插件(由于无法在线安装,所以只能走离线安装)
首先到网址http://updates.jenkins-ci.org/download/plugins/中下载了Email Extension Plugin、Zentimestampplugin、Robot Framework plugin插件:
2) 进入安装插件界面
点击 系统管理——>管理插件——>高级
这时候我们是不是看到了中间有个上传插件的地方(其他地方我们的信息不一样可以不管)。
点击选择文件按钮,选中刚才我们下载的插件,注意每次只能选中一个文件,所以先选择依赖文件。然后点击上传按钮。这样依次就可以将所有的插件离线安装成功了!如下图所示:
D. 配置
1. 系统设置
1) 进入【系统管理】-【系统设置】进行如下配置:设置${BUILD_TIMESTAMP}格式
2) 配置 ExtendedE-mail Notification默认设置
设置邮件内容和发送人:
default content type:设置邮件发送的格式:文本格式或者html格式
Use List-ID Email Header:设置邮件的发送的名称(便于过滤)
Default Recipients:设置默认的收件人
Reply To List:设置默认回复列表
Emergency reroute:相当于一个邮件的转发(邮件先发送到这里,然后在进行进一步处理)
Excluded Recipients:设置接收的黑名单(就是不发送给这些人)
Default Subject:设置默认的邮件主题
Maximum Attachment Size:这只邮件附件的最大值
Default Content:设置邮件的默认内容(里面可以引用一些环境变量的参数,或者插件的一些变量)
Default Pre-send Script:在发送邮件前执行的脚本
邮件通知:这是默认的邮件发送工具,配置和extemail插件设置差不多,只是不能设置邮件的默认发送策略,和邮件发送的内容等信息
【user name:认证的邮箱;password:认证的密码(并非邮箱的密码,是开启smtp时给的一串字符);如果邮箱是ssl链接,就需要勾选use ssl;smtp port :如果你的smtp服务不是465的端口,需要配置对应的端口;charset:邮件编码设置】
注:这里的密码并不是我们邮箱真正的密码,这是QQ邮箱为了给第三方客户端登录的授权码,QQ邮箱是默认关闭SMTP的,所以我们还需要去开通QQ邮箱的SMTP服务,否则第三方客户端无法正常发送邮件。
QQ邮箱开通的SMTP服务步骤如下:
根据提示发送信息,之后QQ会给一个授权码,把该授权码,填到Extended E-mail Notification的密码即可
Extended E-mail Notification默认设置里Default Content的值是填写 ${SCRIPT,template=”robot_results.groovy”}设置这个模板:
在$Jenkins_Home/email-templates目录(如果没有email-templates请自行创建)下创建一个robot_results.groovy文件,内容如下:
robot_results.groovy文件下载地址:https://download.csdn.net/download/glongljl/10396246
其中Jenkins_Home的路径不知道在哪里的话,你可以去看一下系统设置页面,上面有写有:
2. 创建任务
3. 任务的配置
1) General
选中“Restrict where this project can be run”,其LabelExpression填写“master”
2) 源码管理
3) 构建触发器
4) 构建环境
5) 构建
如果在Windows系统中搭建jenkins的话,在构建中,选择“Execute Windows batch command”,输入pybot.bat d:\test.txt (这只是举个例子,具体执行哪个目录下的哪些case,根据实际情况决定)
如果不清楚pybot.bat的用法,可以用RIDE跑一个用例,看command信息,先直接拿过来调试用用
6) 构建后操作
Robot results:
构建后的操作,选择“PublishRobot Framework test results”
*Directory ofRobot output 填一个本地路径,要根据你的output文件放在哪里了,默认可以不填
*Thresholds forbuild result 阀值设置,如80%和100%,这里应该是测试用例执行成功率和通过率的设置
注:如果不知道Directoryof Robot output填什么路径,可以通过控制台输出进行定位,如下:
其实report.html和log.html的输出路径是在启动脚本控制的,如下:
Email 信息:
点击“增加构建后操作步骤”,然后点击“Editable Email Notification”,进入邮件内容详细配置界面。
Default Subject: 邮件主题,可以书写成:XXX项目自动化测试通知:$PROJECT_NAME- Build # $BUILD_NUMBER - $BUILD_STATUS! 分析下这几个参数什么意思:$PROJECT_NAME 构建项目的名称,也就是selenium_2_combat;# $BUILD_NUMBER 构建的号码;$BUILD_STATUS构建状态,这几个参数,它会自动读取,按照这种格式书写即可。
Default Content:邮件内容,这块是重点,最能体现报告的重点,我们需要输入以下内容:
<hr/>
(本邮件是程序自动下发的,请勿回复!)<br/><hr/>
项目名称:$PROJECT_NAME<br/><hr/>
构建编号:$BUILD_NUMBER<br/><hr/>
构建状态:$BUILD_STATUS<br/><hr/>
触发原因:${CAUSE}<br/><hr/>
测试报告:<ahref="http://192.168.1.106:8080/job/$PROJECT_NAME/ws/autotest/result/test-report/power-emailable-report.html">http://192.168.1.106:8080/job/autotest/ws/autotest/result/test-report/power-emailable-report.html</a><br/><hr/>
构建日志地址:<ahref="${BUILD_URL}console">${BUILD_URL}console/</a><br/><hr/>
构建地址:<ahref="$BUILD_URL">$BUILD_URL</a><br/><hr/>
构建报告:<ahref="${BUILD_URL}testReport">${BUILD_URL}testReport/</a><br/><hr/>
变更集:${JELLY_SCRIPT,template="html"}<br/><hr/>
其中的红色字体需要修改成自己电脑的IP地址,这样别人才能访问到jenkins上的测试结果。
点击页面上的Advanced settings设置什么时候触发发送邮件的功能:
把默认的trigger给删除掉,然后新增一个trigger,然后选择Always选项,如此便不管构建成功还是失败都会发送邮件。
点击应用后保存,项目配置完成!!!
4. 邮件查收
点击“立即构建”
执行之后,结果显示如下:
对应邮箱查收如下
E. Jenkins常错误
1. 反向代理设置错误
其实就是,系统管理-->系统设置里的Jenkins URL没有写对,原因是配置文件/etc/sysconfig/jenkins我修改了jenkins启动端口,这里没有相应修改
Jenkins URL
将localhost修改为真实地址即可
修改后已不再提示代理问题
2. 点击‘立即获取’插件,报unable to find valid certification path to requested target错误
原因是缺少证书
3. 缺少依赖插件
根据提示到http://updates.jenkins-ci.org/download/plugins/下载对应的插件
4. 校验邮箱的联通性
如果Test e-mail recipient没有填邮箱信息,则会报如下错误
5. jenkins邮件配置完后发送测试邮件是成功的,并且也能收到的,构建结束成功后log提示成功,但是没有收到邮件
原因是Extended E-mailNotification 的SMTP服务器配置没有使用Jenkins自身的需要专门配置。在系统配置里面多配置一次就行
6. jenkins调用robot_results.groovy 未生效
配置如下:
任务配置:Default Content引用$DEFAULT_CONTENT变量
$DEFAULT_CONTENT变量配置:${SCRIPT,template="robot_results.groovy"}
robot_results.groovy文件是在$Jenkins_Home/email-templates目录下的
robot_results.groovy内容请看如下:
robot_results.groovy文件下载地址:https://download.csdn.net/download/glongljl/10396246
模板一:
<%
import java.text.DateFormat
import java.text.SimpleDateFormat
%>
<!-- Robot Framework Results -->
<!DOCTYPE html>
<html>
<style type="text/css">
table {width:720px;table-layout:fixed;}
td {width:180px;}
td.title {
background-color:#343A40;
text-align: center;
}
td.suite{background-color:#EEE8AA;}
td.case{background-color:#dff0d8;}
td.head{background-color:#1E90FF;}
td.error {background-color:#FF6666;}
table thead tboday tr td {cellspacing:0px;border:1px;}
h2.span{color:white;}
span.pass{color:#66CC00;}
span.fail{color:#FF3333;}
</style>
<body>
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
actions.each() { action ->
if( action.class.simpleName.equals("RobotBuildAction") ) { // hudson.plugins.robot.RobotBuildAction
robotResults = true
%>
<div>
<table cellpadding="" align="left">
<thead>
<tr>
<td class="title" colspan=""><h2><span>${project.name}</span><span> 自动化测试报告</span></h2></td>
</tr>
<tr>
<td class="case"><b>详细报告</b></td>
<td colspan="" class="case"><a href="${rooturl}${build.url}robot/report/report.html">点击查看报告详情</a></td>
</tr>
<tr>
<td class="head"><b>用例总数</b></td>
<td class="head"><b>通过</b></td>
<td class="head"><b>不通过</b></td>
<td class="head"><b>通过率</b></td>
</tr>
<tr>
<td class="case"><%= action.result.overallTotal %></td>
<td class="case"><b><span class="pass"><%= action.result.overallPassed %></span></b></td>
<td class="case"><b><span class="fail"><%= action.result.overallFailed %></span></b></td>
<td class="case"><%= action.overallPassPercentage %>%</td>
</tr>
<tr>
<td colspan="" class="head"><b>Test Name</b></td>
<td class="head"><b>Status</b></td>
<td class="head"><b>Elapsed Time</b></td>
</tr>
</thead>
<tboday>
<%
def suites = action.result.allSuites
suites.each() { suite ->
def currSuite = suite
def suiteName = currSuite.displayName
//忽略最上层结构两个占位的元素
while (currSuite.parent != null && currSuite.parent.parent != null) {
currSuite = currSuite.parent
suiteName = currSuite.displayName + "." + suiteName
}
%>
<tr>
<td colspan="" class="suite"><b><%= suiteName %></b></td>
</tr>
<%
DateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss")
def execDateTcPairs = []
suite.caseResults.each() { tc ->
Date execDate = format.parse(tc.starttime)
execDateTcPairs << [execDate, tc]
}
//按执行日期、显示名称进行排序
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[].displayName <=> b[].displayName }
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[] <=> b[] }
execDateTcPairs.each() {
def execDate = it[]
def tc = it[]
%>
<tr>
<td colspan="" class="case"><%= tc.displayName %></td>
<td class="case"><b><span style="color:<%= tc.isPassed() ? "#66CC00" : "#FF3333" %>"><%= tc.isPassed() ? "PASS" : "FAIL" %></span></b></td>
<td class="case"><%= tc.getDuration().intdiv()+"分"+(tc.getDuration()-tc.getDuration().intdiv()*).intdiv()+"秒" %></td>
</tr> <%
if(tc.errorMsg != null) {
%>
<tr>
<td class="error"><b><span>错误描述:</span></b></td>
<td class="error" colspan=""><span><%= tc.errorMsg%></span></td>
</tr>
<% }%>
<%
} // tests
} // suites
%>
</tboday>
</table>
</div>
<%
} // robot results
}
if (!robotResults){
%>
<p>No Robot Framework test results found.</p>
<%}%>
</body>
</html>
robot测试报告模板一
模板二:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<style type="text/css">
/*base css*/
a{color:#4a72af}
body{background-color:#e4e4e4}
body,p{margin:;padding:}
img{display:block}
h1,h2,h3,h4,h5,h6{margin: .8em }
h3{font-size:28px;color:#!important;font-family:Arial,Helvetica,sans-serif}
h4{font-size:22px;color:#4a72af!important;font-family:Arial,Helvetica,sans-serif}
h5{font-size:18px;color:#!important;font-family:Arial,Helvetica,sans-serif}
p{font-size:12px;color:#!important;font-family:"Lucida Grande","Lucida Sans","Lucida Sans Unicode",sans-serif;line-height:1.5} table.robotstat {
border: 1px solid black;
border-collapse: collapse;
empty-cells: show;
margin: 0px 1px;
table-layout: fixed;
word-wrap: break-word;
font-size: 1em;
border-width:1px;
} tr.test_column_robot {
background-color:#C6C6C6;
} ol li img{display:inline;height:20px}
/*div styles*/
.news{text-align:center;padding-top:15px;}
.content{width:720px;margin: auto;background-color:white}
.round_border{margin-bottom:5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;margin-top:;font-size:14px;padding:6px;border:1px solid #ccc}
.status{background-color:<%=
build.result.toString() == "SUCCESS" ? 'green' : 'red' %>;font-size:28px;font-weight:bold;color:white;width:720px;height:52px;margin-bottom:18px;text-align:center;vertical-align:middle;border-collapse:collapse;background-repeat:no-repeat}
.status .info{color:white!important;text-shadow: -1px rgba(,,,0.3);font-size:32px;line-height:36px;padding:8px }
.main img{width:38px;margin-right:16px;height:38px}
.main table{font-size:14px;}
.main table th{text-align:right;}
.bottom-message{width:720px;cellpadding:5px;cellspacing:0px}
.bottom-message .message{font-size:13px;color:#aaa;line-height:18px;text-align:center}
.bottom-message .designed{font-size:13px;color:#aaa;line-height:18px;font-style: italic;text-align:right}
img.cartoon {width: 36px; display:inline}
</style>
<body>
<div class="content round_border">
<div class="status">
<p class="info">构建状态 <%= build.result.toString().toLowerCase() %></p>
</div>
<!-- status -->
<div class="main round_border">
<table>
<tbody>
<tr>
<th>项目名称:</th>
<td>${project.name}</td>
</tr>
<tr>
<th>构建轮次:</th>
<td><a
href="${rooturl}${build.url}">${build.displayName}(点击查看此轮构建信息)</a></td>
</tr>
<tr>
<th>构建时间:</th>
<td>${it.timestampString}</td>
</tr>
<tr>
<th>构建时长:</th>
<td>${build.durationString}</td>
</tr>
<tr>
<th>构建缘由:</th>
<td><% build.causes.each() { cause -> %> ${cause.shortDescription} <% } %></td>
</tr>
<tr>
<th>测试报告:</th>
<td><a
href="${rooturl}${build.url}robot">点击查看测试报告详情</a></td>
</tr>
<tr>
<!-- test stat -->
<th>测试统计:</th></br>
<td>
<table id="robotstat" class="robotstat">
<thead>
<tr id="test_column_robot" class="test_column_robot">
<th>测试总用例数</th>
<th>失败用例数</th>
<th>测试通过率</th>
</tr>
</thead>
<tbody>
<tr>
<% def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction") %>
<td>${robotTestResultAction.getTotalCount()}</td>
<td>${robotTestResultAction.getFailCount()}</td>
<td>${robotTestResultAction.getOverallPassPercentage()}%</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<th>变更记录:</th>
<td><a
href="${rooturl}${build.url}changes">点击查看变更记录</a></td>
</tr>
<tr>
<td colspan=""> </td>
</tr>
</tbody> </table> </div>
<!-- main -->
<% def artifacts = build.artifacts
if(artifacts != null && artifacts.size() > ) { %> <div class="artifacts round_border">
<b>Build Artifacts:</b>
<ul>
<% artifacts.each() { f -> %>
<li><a href="${rooturl}${build.url}artifact/${f}">${f}</a></li>
<% } %>
</ul>
</div>
<% } %>
<!-- artifacts --> <% def changeSet = build.changeSet
if(changeSet != null) {
def hadChanges = false
def count = %> <div class="details round_border">
<b>变更详细:</b>
<ol>
<% changeSet.each() { cs ->
hadChanges = true
def aUser = cs.author %>
<li>${cs.msgAnnotated} (${aUser.displayName})
(<a href="${rooturl}${build.url}changes#detail${count}">detail</a>)</li>
<% count ++
} %>
</ol>
</div>
<% } %>
<!-- details -->
</div>
<!-- content --> <table class="bottom-message" align="center">
<tr>
<td class="message">You are receiving this email because you
are relavent with this build<br>
</td>
</tr>
<tr>
<td colspan="" class="designed">designed by @YTO </td>
</tr>
</table>
<!-- bottom message --> </body>
结果邮箱收到时没有读取robot_results.groovy的模板内容
经过分析:
是由于缺少groovy-postbuild插件操作的,安装groovy-postbuild插件
groovy-postbuild插件安装完之后,重新执行计划,邮箱可以获取到模板信息的,如下:
7. Robot Framework - Jenkins 的测试报告打不开
点击邮件的链接
以及点击Jenkins上的链接
结果界面都会报如下错误:
解决办法:
1. 如果你是用命令行开启的
关闭Jenkins,修改开启命令如下,重新开启:
java -Dhudson.model.DirectoryBrowserSupport.CSP= -jar E:\Jenkins\jenkins.war
2. 如果你是用msi安装的
找到jenkins.xml 文件,修改如下
<arguments>-Xrs-Xmx256m -Dhudson.model.DirectoryBrowserSupport.CSP=-Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar"%BASE%\jenkins.war" --httpPort=8080</arguments>
3. 如果你是用tomcat 启动的
有个临时的解决方法
打开jenkins 首页——>进入系统管理——>进入脚本命令行
在输入框输入如下代码,并执行
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","")
注:方法3 都可以使用,但是重启后就失效了,需要重新执行
4. 访问端解决办法
以Firefox为例:
到 about:config 设置
security.csp.enable= false
之后问题正常显示如下:
---------------------
作者:glong168
来源:CSDN
原文:https://blog.csdn.net/glongljl/article/details/80212611
版权声明:本文为博主原创文章,转载请附上博文链接!
RobotFramework与Jenkins集成发送邮件的更多相关文章
- RobotFramework与Jenkins集成后构建成功率高于设置阈值但总是显示失败
摘要:robot执行后总是失败 1.在配置jenkins的job时,添加构建步骤Execute Windows batch command,输入执行robotframework测试用例命令 2.然后j ...
- RobotFramework与Jenkins集成后失败用例重跑
Jenkins的执行Windows批处理命令填写如下: call pybot.bat -i 1adsInterface 01_测试用例\接口测试用例\adsInterface.txt call pyb ...
- RobotFramework与Jenkins集成后发送groovy报告(比别处多了用例作者信息)
https://www.cnblogs.com/gcgc/p/10037891.html 这篇文章中最终的发送报告是这个样子,每天大家看到这封邮件后也不知道是不是自己的用例错误了,导致大家不积极回复邮 ...
- JMeter - 连续性能测试 - JMeter + ANT + Jenkins集成 - 第2部分
目标: 创建包含性能测试流程的持续交付管道,以尽早检测任何与性能相关的问题. 通常,全面的性能测试将在分段/预生产环境中完成,该环境可能与您的生产环境相同.在完成QA功能/回归验证后,将代码推送到分段 ...
- Jenkins 集成打包和上传 App Store 的冲突
周一下午用 Jenkins 集成打包,遇到了一个很奇怪的问题,之前上传到 APP Store 的时候 Build Settings->“Code Signing Resource Rules P ...
- Jmeter+Jenkins集成html报告显示问题
在J meter+Jenkins集成生成的html报告时,出现如下问题:无法正常显示表格,detail内容无法折叠和展开操作. 解决方法:执行下列脚本行 在Jenkins :系统管理--脚本命令行 S ...
- jenkins 集成 redmine 账户验证的方案
jenkins 集成 redmine 账户验证的方案 赖勇浩(http://laiyonghao.com) 动机 Jenkins 是最著名的持续集成工具,又因为它开源免费.插件众多,成为了许多团队做持 ...
- Jenkins集成taffy进行自动化测试并输出测试报告
本文主要介绍Jenkins集成taffy/nose框架进行自动化测试并输出测试报告方法. 0. 测试环境 Jenkis主节点部署在CentOS系统上,子节点为Win10 64位系统(即我们本机运行自动 ...
- Jenkins集成Docker镜像实现自动发布
1. 思路&流程 Jenkins集成Docker镜像实现自动发布与Jenkins发布mavne项目思路一样总体流程 为:Jenkins 拉去远端源码 -- gitl实现应用打包 -- jenk ...
随机推荐
- 【airflow实战系列】 基于 python 的调度和监控工作流的平台
简介 airflow 是一个使用python语言编写的data pipeline调度和监控工作流的平台.Airflow被Airbnb内部用来创建.监控和调整数据管道.任何工作流都可以在这个使用Pyth ...
- 封装baseservice
package com.huawei.base; import java.io.Serializable;import java.util.List; public abstract class Ba ...
- mysql存储过程(procedure)
#创建带参数的存储过程 delimiter // ),out p int) begin ; end // delimiter call pro_stu_name_pass(@n,@p); select ...
- java算法 第七届 蓝桥杯B组(题+答案) 1.煤球数目
1.煤球数目 (结果填空) 有一堆煤球,堆成三角棱锥形.具体:第一层放1个,第二层3个(排列成三角形),第三层6个(排列成三角形),第四层10个(排列成三角形),....如果一共有100层,共有多少 ...
- Fresnel Reflection Shader
[Fresnel Reflection] One of the most used types of reflections is the Fresnel reflection. One of the ...
- emulator: Trying to vcpu execute at eip:6d4053
- 【CodeForces148D】Bag of mice
题意 dragon和princess玩一个游戏.开始的时候袋子里有w个白老鼠和b个黑老鼠.两个人轮流从袋子里面往外摸老鼠.谁先拿到白老鼠谁先获胜.dragon每次抓出一只老鼠,剩下老鼠里面都会有一只跳 ...
- Hibernate批量抓取
------------------siwuxie095 Hibernate 批量抓取 以客户和联系人为例(一对多) 1.批量抓取 同时查询多个对象的关联对象,是 Hibernate 抓取策略的一种 ...
- php魔术方法__SET __GET
__SET 设置一个不可访问的属性的时候 调用_set方法 __GET 获取一个不可访问的属性的时候 调用_get 方法 <?php class stu{ private $a; priva ...
- 什么是响应式编程——响应式Spring的道法术器
响应式编程之道 1.1 什么是响应式编程? 在开始讨论响应式编程(Reactive Programming)之前,先来看一个我们经常使用的一款堪称“响应式典范”的强大的生产力工具——电子表格. 举个简 ...