1. 程式人生 > >基於 jmeter 和 shell 的介面效能自動化

基於 jmeter 和 shell 的介面效能自動化

jmeter+shell

1. 總體需求

由於效能測試中涉及的查詢介面多,版本迭代頻繁,版本更新後自動跑一輪查詢業務的效能,可以及時發現一些開發修復bug觸發的非預期的bug,利用晚上時間快速重測效能介面可以解放人工測試的時間,讓測試人員可以把精力集中在測試複雜介面,調優分析效能瓶頸上。

2. 實現流程

自動化的場景模擬真實手工測試,操作步驟和手工測試一樣。

 

 

3.準備工作

準備軟體:

系統環境:CentOS release 6.7 (Final)
核心版本:Linux localhost 2.6.32-573.7.1.el6.x86_64
測試工具:apache-jmeter-2.13 

http://jmeter.apache.org/download_jmeter.cgi
執行JDK環境:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
python環境:Python 2.6.6
伺服器監控nmon:http://nmon.sourceforge.net/pmwiki.php?n=Site.Download

4.具體實現

4.1用例執行

Jmeter的執行支援命令列的方式執行,並且會有一個粗略報告,我們取這個報告裡面的執行結果並儲存下來 
Jmeter的執行結果:

[email protected]
bin]# ./jmeter -n -t singin.jmx Creating summariser <summary> Created the tree successfully using singin.jmx Starting the test @ Mon Dec 14 16:42:33 CST 2015 (1450082553651) Waiting for possible shutdown message on port 4445 summary + 1 in 1s = 1.3/s Avg: 268 Min: 268 Max: 268 Err: 0
(0.00%) Active: 1 Started: 1 Finished: 0 summary + 2 in 0s = 50.0/s Avg: 17 Min: 14 Max: 20 Err: 0 (0.00%) Active: 0 Started: 1 Finished: 1 summary = 3 in 1s = 3.7/s Avg: 100 Min: 14 Max: 268 Err: 0 (0.00%) Tidying up ... @ Mon Dec 14 16:42:34 CST 2015 (1450082554551) ... end of run

 

由sumary統計行可以得到我們需要收集的測試結果:

 

 

 

主流程指令碼
#/bin/bash

source /etc/profile
Jmeter_Home='/usr/local/apache-jmeter-2.13'
TestReport='/data/loadtest/report'
LogDIR='/data/loadtest/log'
Date=`date +"%F"`
cd /data/loadtest/
>summary.txt
#清理上次執行結果
run_test()
{
#獲取測試用例
 for i in `find ./testcase/ -name *.jmx|awk -F '.' '{print $2}'`
  do 
  casename=`echo "$i"|awk -F '/' '{print $4}'`
  >log/${casename}.txt
  echo -n "$i ">>summary.txt
  #發起監控
  ./monitor.sh >/dev/null 2>&1 &
  #開始執行測試
  $Jmeter_Home/bin/jmeter -n -t /data/loadtest${i}.jmx >>log/${casename}.txt &
  sleep 310
  #如果執行310s還未結束,強制終止執行
  ps -ef | grep java |grep -v grep | awk '{print $2}' |xargs kill -9 
  sleep 3
  #提取結果
  grep 'summary =' log/${casename}.txt| tail -1 |awk -F '[\t / (]+' '{if($7>10000 && $17<10.00){printf("%s %d %d %d %.2f% pass ",$7,$10,$3,$16,100-$17)}else{printf("%s %d %d %d %.2f%% fail ",$7,$10,$3,$16,100-$17)}}'>>summary.txt
  cat monitor.txt >>summary.txt
  echo '' >> summary.txt
  #獲取關鍵日誌
  ssh 10.1.30.54 'tail -n 300 /data/logs/fcuh-user/catalina.out'>${LogDIR}${i}.log
 done
}
run_test
sleep 3
#生成html報告
sh genHTML.sh
sleep 1
#傳送郵件
python sendmail.py

 

 

4.2伺服器監控

伺服器資源收集方面,選用的是nmon監控工具,因為它可以後臺收集結果儲存到檔案。由於每個用例測試5分鐘,所以只需要監控300秒,每5s監控一次,對應命令:

nmon -f -t -s5 -c60 -F /data/test.nmon
 

測試用例跑完再讀取這個結果檔案,獲取有用的資訊 
當前只統計了磁碟io和cpu的佔用率資訊,原始檔案儲存在本地目錄,如果需要,可以手動檢視到。

監控指令碼:
#!/bin/bash
#讀取監控伺服器列表
SERVERLIST=`cat serverlist`
DATE=`date +'%F'`
mkdir -p /data/loadtest/monitor/$DATE
TIME=`date +'%T'`
#發起監控
for i in $SERVERLIST
do 
  ssh $i 'nmon -f -t -s5 -c60 -F /data/test.nmon >/dev/null 2>&1 &'
done
#監控5分鐘
sleep 303
>monitor.txt
#收集監控結果,儲存到monitor.txt
for i in $SERVERLIST
do
 scp $i:/data/test.nmon /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon
 io=`cat /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon|grep "DISKBUSY,T" | awk -F ',' '{sum+=$3} END {printf("%.2f%",sum/NR)}'`
 cpu=`cat /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon|grep "CPU_ALL,T" | awk -F ',' '{sum+=$6} END {printf("%.2f%",100-sum/NR)}'`
 #net=`cat /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon|grep "NET,T"|awk -F ',' '{sum_r+=$4}{sum_w+=$6} END {print sum_r/NR,sum_w/NR}'`
 echo -n "${cpu} ${io} ">>monitor.txt
done

 

 

將用例執行結果和監控結果都彙總到summary.txt裡 
生成的格式如下,方便後面生成html格式的報告

[[email protected] loadtest]# cat summary.txt 
/testcase/user/獲取使用者自己的資訊 10748.6 8 3225296 0 100.00% pass 32.87% 5.34% 81.59% 2.12% 0.15% 1.78% 12.13% 32.83% 17.18% 6.14% 
/testcase/user/未讀訊息數 11487.4 7 3446960 0 100.00% pass 32.33% 12.57% 69.02% 1.86% 0.18% 1.74% 13.55% 35.85% 18.56% 7.65%
伺服器監控指令碼
#!/bin/bash

SERVERLIST=`cat serverlist`
DATE=`date +'%F'`
mkdir -p /data/loadtest/monitor/$DATE
TIME=`date +'%T'`
for i in $SERVERLIST
do 
  ssh $i 'nmon -f -t -s5 -c60 -F /data/test.nmon >/dev/null 2>&1 &'
done

sleep 303
>monitor.txt
for i in $SERVERLIST
do
 scp $i:/data/test.nmon /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon
 io=`cat /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon|grep "DISKBUSY,T" | awk -F ',' '{sum+=$3} END {printf("%.2f%",sum/NR)}'`
 cpu=`cat /data/loadtest/monitor/$DATE/${i}_${TIME}.nmon|grep "CPU_ALL,T" | awk -F ',' '{sum+=$6} END {printf("%.2f%",100-sum/NR)}'`
 echo -n "${cpu} ${io} ">>monitor.txt
done

 

4.3生成html報告

#!/bin/sh
>index.html
echo "<html><head><META http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>使用者端自動化效能測試報告</title>">>index.html
echo `cat style.css`>>index.html
(
cat <<EOF
<script language="JavaScript">
               function show_detail(detail){
                           if(detail.style.display=="none"){
                           detail.style.display="";
                           }
                           else{
                           detail.style.display="none";
                           }
                           }
                           </script>
EOF
)>>index.html
echo "</head><body><h1>使用者端自動化效能測試報告</h1><hr size="1">">>index.html
sum=`cat summary.txt | wc -l`
sucess=`cat summary.txt|grep pass |grep -v grep|wc -l`
fail=`expr $sum - $sucess`
rate=`echo "$sucess $sum"|awk '{printf("%.2f%%",$1/$2*100)}'`
(
cat <<EOF
<table><tr><td>
<h2>結果彙總</h2>
<table width="60%" cellspacing="2" cellpadding="5" border="0" class="details" align="left">
<tr><th>總介面數</th><th>成功介面數</th><th>失敗介面數</th><th>測試通過率</th></tr>
<tr align="center"><td>$sum</td><td>$sucess</td><td>$fail</td><td>$rate</td></tr>
</tr></table>
</td></tr>
EOF
)>>index.html
(
cat <<EOF
<tr><td>
<h2>概要結果</h2>
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="details" align="left">
<tr valign="top">
<th>測試介面</th><th>每秒請求數(tps)</th><th>平均響應時間(ms)</th><th>總事務數</th><th>失敗事務數</th><th>事務成功率</th><th>測試結果</th>
</tr>
<tr valign="top" class="">
EOF
)>>index.html
cat summary.txt |while read line
do 
  echo $line | awk '{if($7=="pass"){print "<tr><td>"$1"</td><td>"$2"</td><td>"$3"</td><td>"$4"</td><td>"$5"</td><td>"$6"</td><td class=\"Pass\">"$7"</td></tr>"}else{print "<tr><td>"$1"</td><td>"$2"</td><td>"$3"</td><td>"$4"</td><td>"$5"</td><td>"$6"</td><td class=\"Failure\">"$7"</td></tr>"}}'>>index.html
done
echo "</tr></table></td></tr>">>index.html
echo "<table><tr><td><font color="red"><b>測試結果pass標準:tps>10000且事務成功率>90%</b></font><td></tr><tr><td><h2><a href=\"javascript:show_detail(detail)\">詳細結果檢視附件</a></h2></td></tr></table>">>index.html
#echo "<div class=\"page_details_expanded\" id=\"detail\" style=\"display:none;\" width=\"95%\">">>index.html
(
cat <<EOF
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="details" align="left" id="detail" style="display:none">
<tr valign="top">
<th>測試介面</th><th>每秒請求數tps</th><th>平均響應時間(ms)</th><th>總事務數</th><th>失敗事務數</th><th>成功率</th><th>測試結果</th><th>nginx伺服器cpu</th><th>nginx伺服器io</th><th>web伺服器cpu</th><th>web伺服器io</th><th>service伺服器cpu</th><th>service伺服器io</th><th>主資料庫伺服器cpu</th><th>主資料庫伺服器io</th><th>從資料庫伺服器cpu</th><th>從資料庫伺服器io</th>
</tr>
<tr valign="top" class="">
EOF
)>>index.html
j=1
for i in `cat summary.txt`
do 
   if [ `expr $j % 17 ` != 0 ]; then 
      echo '<td align="left">'$i'</td>'>>index.html
   else
      echo '<td align="left">'$i'</td></tr>'>>index.html
   fi
   j=`expr $j + 1`
done
echo "</tr></table></td></tr></table></body></html>">>index.html

 

 
html樣式表
<style type="text/css">
body {
        font:normal 68% verdana,arial,helvetica;
        color:#000000;
     }
table tr td, table tr th {
         font-size: 78%;
     }
table.details tr th{
         color: #ffffff;
         font-weight: bold;
         text-align:center;
         background:#2674a6;
         white-space: nowrap;
     }
table.details tr td{
        background:#eeeee0;
        white-space: nowrap;
     }
h1 {
        margin: 0px 0px 5px; font: 265% verdana,arial,helvetica
   }
h2 {
        margin-top: 1em; margin-bottom: 0.5em; font: bold 185% verdana,arial,helvetica
   }
h3 {
        margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
   }
.Failure {
        font-weight:bold; color:red;
   }
.Pass {
        font-weight:bold; color:green;
   }
</style>
 

4.4傳送測試結果郵件

發郵件指令碼
#!/usr/bin/env python
#coding: utf-8  
import string
import smtplib
import os
import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.header import Header

today = datetime.date.today()
sender = '[email protected]'
receiverlist = ["[email protected]","[email protected]","[email protected]"]  
subject = '%s %s' % ('使用者端自動化效能測試報告',today)
smtpserver = 'smtp.exmail.qq.com'
username = '[email protected]'
password = 'xxx'
f = open('index.html',"r")
content = f.read()

#msg = MIMEText(content,'html','utf-8')
msg = MIMEMultipart()
msg.attach(MIMEText(content,'html','utf-8'))

msg['From'] = '[email protected]'
msg['to'] = ','.join(receiverlist)
msg['Subject'] = subject

att=MIMEText(open('index.html','rb').read(),'base64','gb2312')
att["Conten-Type"]='application/octet-stream'
att["Content-Disposition"]='attachment;filename="Load test result.html"'
msg.attach(att)

smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
#smtp.set_debuglevel(1)
smtp.login(username, password)
smtp.sendmail(msg['From'],msg['to'],msg.as_string())
smtp.quit()
 

測試結果截圖: 

 

 


這裡還涉及到ssh免密碼登入、jmeter測試用例的編寫,沒有細說,其實百度一下就知道了