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="4" align="left">
                <thead>
                    <tr>
                        <td class="title" colspan="4"><h2><span>${project.name}</span><span>  自動化測試報告</span></h2></td>
                    </tr>
                    <tr>
                        <td class="case"><b>詳細報告</b></td>
                        <td colspan="3" 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="2" 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="4" 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[1].displayName <=> b[1].displayName }
    execDateTcPairs = execDateTcPairs.sort{ a,b -> a[0] <=> b[0] }
    execDateTcPairs.each() {
        def execDate = it[0]
        def tc = it[1]  
%>
                    <tr>  
                        <td colspan="2" 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(60000)+""+(tc.getDuration()-tc.getDuration().intdiv(60000)*60000).intdiv(1000)+"" %></td>  
                    </tr>  
        
<%
        if(tc.errorMsg != null) {
%>
                    <tr>
                        <td class="error"><b><span>錯誤描述:</span></b></td>
                        <td class="error" colspan="3"><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:0;padding:0}
img{display:block}
h1,h2,h3,h4,h5,h6{margin:0 0 .8em 0}
h3{font-size:28px;color:#444!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:#444!important;font-family:Arial,Helvetica,sans-serif}
p{font-size:12px;color:#444!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:0 auto;background-color:white}
.round_border{margin-bottom:5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;margin-top:0;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:0 -1px 0 rgba(0,0,0,0.3);font-size:32px;line-height:36px;padding:8px 0}
.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="2"> </td>
                    </tr>
                </tbody>

            </table>

        </div>
        <!-- main -->
        <% def artifacts = build.artifacts
            if(artifacts != null && artifacts.size() > 0) { %>

        <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 = 0 %>

        <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="2" 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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM