LoadRunner腳本篇

1   概述

腳本錄製編寫是性能測試的一個重要環節。在性能測試過程當中,虛擬用戶模擬真實用戶使用被測系統,這個「模擬」的過程正是經過性能測試腳原本實現的。所以,編寫一個準確無誤的腳本對性能測試有相當重要的意義。完成性能測試腳本包括兩個步驟:腳本錄製和腳本編寫,本文重點關注腳本編寫。javascript

2   腳本錄製

2.1.錄製方式html

HTTP協議腳本錄製可選兩種方式:基於HTML和基於URL。選擇哪一種錄製方式的原則以下:基於瀏覽器的HTTP應用系統選擇HTML,基於其餘方式的HTTP應用系統選擇URL。java

2.2.錄製注意點node

取消錄製期間自動關聯功能;web

若是部分測試腳本出現問題,須要從新錄製,能夠只錄制存在問題的片段腳本,方法是不選中錄製啓動對話框中的Record the application startup。數組

3   腳本編寫

3.1.經常使用技術瀏覽器

LoadRunner性能測試腳本編寫經常使用的技術包括參數化,關聯,邏輯控制和腳本模塊化。服務器

3.1.1.參數化併發

參數化就是將腳本中的常量轉化爲變量的過程。經過錄制生成的腳本全部的數據都是常量,爲了達到向服務器發送的數據多樣化的目的,須要將一些數據常量轉化爲變量。app

3.1.2.關聯

關聯就是查找動態數據,並把查詢到的數據以參數的形式保存起來。在B/S或者C/S系統中,服務器返回給客戶端的數據有些是動態改變的,例如客服系統的人工來話流水號和工做流系統的工單流水號。當打開工單生成頁面後,工單流水號已經從服務器端獲取到了,而在提交工單步驟,須要將該流水號返回給服務器。所以,在提交工單以前,在腳本中必須得到流水號。得到流水號的方法就是關聯。

使用關聯功能動態保存的參數跟直接經過參數化生成的參數是一致的。惟一不一樣的是,經過參數化生成的參數在腳本中能夠高亮顯示。

3.1.3.邏輯控制

業務系統在實際應用中,業務操做步驟間每每存在邏輯。好比,客服3.0工做流系統,業務表明處理工單,若是待辦區沒有工單等待處理,則先從工單池中提取工單到待辦區,而後進行處理,而且須要優先處理超時或即將超時的工單。在工單處理的性能測試腳本中,也必須聽從這種業務邏輯。

LoadRunner性能測試腳本採用C語言,所以腳本邏輯控制同C語言一致,使用if,switch,while/for/do控制結構。

3.1.4.腳本模塊化

腳本模塊化的目的是:提升腳本可讀性、可重用性和腳本生產效率。腳本模塊化的本質是抽取函數,一些很通用的函數甚至能夠封裝爲DLL。模塊化性能測試腳本的思想跟自動化測試的ActionWord有類似之處。

例如:客服3.0系統的登陸功能,不管是工做流、知識庫、公告便籤仍是培訓考試,它們都使用相同的登陸頁面。咱們能夠把登陸腳本抽取爲一個函數csp_login(char *staffno,char * password),須要登陸操做時,不須要錄製和拷貝腳本,只要調用這個函數就能夠了。

注意:並非全部的腳本代碼塊都須要作模塊化處理,只有那些穩定不變、而且常常用到的代碼塊才須要作模塊化處理。不作得不償失的事。

3.2.典型函數

LoadRunner中,經常使用的函數有不少,這裏只介紹編寫性能測試腳本過程當中那些必然用到的函數。本文重點關注這些典型函數的應用場合及注意點,至於函數詳細使用說明請參見LoadRunner幫助文檔。

3.2.1.事務相關

3.2.1.1. lr_start_transaction/lr_end_transaction

功能:事務開始/結束標記。

應用場合:須要統計某一段代碼塊執行所須要的時間,這兩個函數須要成對使用。

舉例:工做流系統性能測試中有一個需求,300人在線,提交工單操做平均響應時間在3秒之內,則須要在提交工單請求步驟以前插入lr_start_transaction,提交工單請求步驟以後插入lr_end_transaction。

注意點:這兩個函數只是標記函數,用於標記事務開始/結束,所以能夠嵌套使用,即事務中還能夠包含子事務。

 

3.2.1.2. lr_think_time

功能:模擬思考時間,即等待時間。

應用場合:在線用戶測試,爲了讓每個虛擬用戶模擬一個真實用戶的行爲,即讓一個虛擬用戶對系統產生的壓力跟真實用戶至關,就必須使用這個函數。這是由於,用戶在使用系統的過程當中,從一個操做轉換到另外一個操做,是須要時間的,這個時間就是思考時間。

舉例:客服3.0工做流系統在線用戶測試。對於工單查詢操做,輸入查詢條件後提交查詢,從輸入查詢條件至提交查詢的時間間隔就是思考時間。由於LoadRunner沒法模擬鍵盤輸入的過程,它只能模擬鍵盤輸入的等待時間,此時須要在提交查詢的那個動做前插入lr_think_time函數。

注意點:在錄製腳本中,原子事務內不要包含lr_think_time函數,不然該思考時間將被統計到事務響應時間中,形成結果不許確。另外lr_think_time是否啓做用,可經過runtime-seting進行設置。

注:原子事務指那些不能再分割爲更小事務的事務,它常常指一個單一的業務操做,一般表現爲一個URL請求。

 

3.2.1.3. lr_rendezvous

功能:在Vuser腳本中設置集合點。

應用場合:併發測試。

舉例:客服3.0培訓考試系統,100人同時打開同一份試卷。則須要在打開試卷的語句前插入lr_rendezvous函數,並在場景中設置集合點策略。

注意點:非併發測試,例如在測試系統的處理能力時,最好不要設置集合點,由於一旦設置了集合點,將致使一些VUser處於等待狀態,在這等待過程當中服務器將是空閒的,這將致使不能準確的測試出服務器的真實性能水平。集合點更多用於發現系統的併發問題。

 

3.2.2.參數化/關聯

3.2.2.1.lr_save_string/lr_save_int

功能:將某一字符串/整型保存爲參數。

應用場合:有些變量的值經過C語言生成,以後在測試腳本中要使用這些變量。

舉例:客服3.0業務配置臺系統增長業務表明操做,業務表明的工號和姓名使用C語言函數生成。工號和姓名分別保存在staff_no和staff_name變量中,則在腳本中可使用lr_save_int(staff_no,"staffno"),lr_save_string(staff_name, "stafffname")將工號和姓名參數化。

注意點:無。

 

3.2.2.2.web_reg_save_param

功能:在服務器返回的文本中查找一個或者多個字符串,並將搜索到的字符串值保存在參數中。

應用場合:在B/S或者C/S系統中,服務器返回給客戶端的數據有些是動態改變的,在腳本的下一個步驟中,須要使用該動態數據。這時,就須要使用關聯得到該動態數據。

舉例:客服3.0工做流系統,工單辦理每次都從待辦區中打開第一條工單,爲打開第一條工單,須要獲取第一條工單的完整URL(包括URL中的parameter及其值),而每一次進入待辦區,第一條工單有多是不同的。爲獲取第一條工單的URL,將打開工單的URL作關聯。已知打開待辦區操做得到的HTML有以下片段:

<a href="#"onclick="javascript:openseviceforprocess('/iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200','false');">

可在打開待辦區的操做前插入以下語句:

web_reg_save_param("tt_url", "LB=javascript:openseviceforprocess('","RB=','false')", "Ord=1","IgnoreRedirections=Yes", "Search=Body","RelFrameId=1", LAST );

運行腳本後,tt_url的值爲:

/iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200

這個URL就是打開第一條工單的URL,有了URL,即可打開工單。

注意點:

(1)LoadRunner工具只能識別文本,在HTTP協議中只能識別HTML文檔,所以關聯的依據是HTML源碼,而不是通過瀏覽器解析後的可視化文本。這一點很重要。

(2)關聯還能將多個匹配的參數保存在數組中,方法是指定ORD的屬性值爲ALL,以後經過「{參數名_1}」, 「{參數名_2}」, 「{參數名_3}」格式可得到數組元素的值。

(3)該函數有一個屬性NOTFOUND,默認值爲ERROR,也就是說,若是找不到要查找的數據,將報出錯誤,在必要的時候,例如腳本邏輯控制須要,能夠將NOTFOUND的屬性值設爲WARNING,這樣LoadRunner將不產生錯誤。

 

3.2.2.3.lr_save_searched_string

功能:在某一個字符緩衝區中搜索指定的字符串,並將搜到的字符串保存在參數中。

應用場合:可配合LoadRunner的關聯功能,靈活獲取服務器端返回的數據。

舉例:客服3.0工做流系統,工單處理每次都從待辦區中打開第一條工單,打開工單的URL已經經過關聯保存在tt_url參數中,在工單處理提交時,須要使用serviceNo,serviceID,nodeID,dealID,tt_url的值以下:

/iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200

可以使用如下函數保存serviceNo,serviceID,nodeID,dealID的值。

//保存serialNo,serviceID,nodeID,dealID參數

int getTTData(){

 int i = 0;int j=0;

char *tt_url = lr_eval_string("{tt_url}");

 int len= strlen(tt_url);

 while(tt_url[i]!='='){i++;} while(tt_url[j]!='&'){j++;}

 lr_save_searched_string(tt_url,len,0,"serialNo",1,j-i-1,"serialNo");

 i++;j++;while(tt_url[i]!='='){i++;} while(tt_url[j]!='&'){j++;}

lr_save_searched_string(tt_url,len,0,"serviceID",1,j-i-1,"serviceID");

  i++;j++;while(tt_url[i]!='='){i++;}  while(tt_url[j]!='&'){j++;}

 lr_save_searched_string(tt_url,len,0,"nodeID",1,j-i-1,"nodeID");

  i++;j++; while(tt_url[i]!='='){i++;}  while(tt_url[j]!='&'){j++;}

lr_save_searched_string(tt_url,len,0,"dealID",1,j-i-1,"dealID");

return 0;

}

注意點:

 

3.2.2.4.lr_save_datetime

功能:將時間保存爲參數。

應用場合:應用系統須要把時間數據提交給服務器端。

舉例:客服3.0工做流系統活動工單查詢,默認查詢從當天開始的最近三天工單。 則查詢的開始時間和結束時間可用lr_save_datetime獲取。

lr_save_datetime("%y-%m-%d00:00", DATE_NOW-2*ONE_DAY, "queryBeginTime");    

lr_save_datetime("%y-%m-%d23:59", DATE_NOW, "queryEndTime");

注意點:

 

3.2.2.5. web_save_timestamp_param

功能:將當前時間戳保存爲參數。

應用場合:應用系統須要把時間戳提交給服務器端。

舉例:多媒體坐席客戶端,在向MClient提交信息時,須要附帶客戶端的時間戳,則可使用該函數獲取當前時間戳。

注意點:與lr_save_datetime不一樣的是,本函數保存的是時間戳,而lr_save_datetime保存的是日期和時間。

 

3.2.2.6.lr_eval_string

功能:將某一字符串中包含的全部參數替換爲真實值,並返回替換後的字符串。

應用場合:欲查看某一參數的值,可以使用該函數。

舉例:客服3.0工做流系統,生成工單時打開工單頁面準備工單提交,提交以前想查看已經過關聯保存的serialNo參數的值。方法以下:

lr_output_message(lr_eval_string("TheserialNo is {serialNo}"));

注意點:若是不存在該參數,將把「{參數名}」看成普通字符串輸出。如本例,若是不存在serialNo參數,則輸出:The serialNo is {serialNo}。

 

3.2.3.驗證點

3.2.3.1.web_reg_find

功能:在HTML文檔中查找指定的字符串。

應用場合:該函數是檢查點函數,在腳本中須要插入檢查點的地方使用。

舉例:客服3.0工做流系統,提交工單生成後,須要驗證工單是否提交成功。則可根據頁面提示「工單生成成功」進行驗證。在提交生成工單步驟前插入:

web_reg_find("Text=工單生成成功",LAST);

注意點:該函數是註冊型參數,須要在請求服務器數據步驟以前插入該函數。與該函數功能相似的函數是web_find,可是web_find只對HTML方式的腳本起做用,對URL方式腳本則不起做用,並且web_find函數效率低下,已被廢棄。

 

3.2.3.2. web_image_check

功能:判斷某一個圖片是否存在HTML頁面中。

應用場合:同web_reg_find函數同樣,該函數也是檢查點函數,在腳本中須要插入檢查點的地方使用。

舉例:客服3.0培訓考試系統併發測試,50我的同時打開試卷,爲了驗證打開試卷成功,根據試卷中的圖片public/images/onexam.gif進行驗證:

web_image_check("web_image_check","Src=public/images/onexam.gif",LAST);

注意點:要使該函數生效,須要在runtime-seting中將打開。與web_reg_find不同的是,該函數不是註冊型函數,所以須要在請求返回步驟以後插入該函數。上文提過,LoadRunner只能識別文本,所以web_image_check函數其本質仍然是文本驗證,徹底能夠用web_reg_find替代,並且強烈推薦使用web_reg_find做爲檢查點函數。

 

3.2.4.日誌輸出

3.2.4.1. lr_output_message

功能:將VUser的消息打印到日誌文件和輸出窗口中,打印的消息帶有腳本行信息。

應用場合:方便查看運行信息,輔助問題定位。

舉例:客服3.0系統,登陸工號已經參數化,調試腳本時將當前的登陸工號輸出到Replay Log窗口中。代碼以下:

lr_output_message("Thestaffno is %s",lr_eval_string("{staffno}"));

注意點:與該函數具備相似功能的還有:lr_debug_message,lr_log_message lr_message,lr_error_message它們之間的不一樣之處這裏不做詳細介紹,請參見LoadRunner幫助文檔。

 

3.2.4.2. lr_vuser_status_message

功能:將VUser的消息輸出到場景運行的VUser狀態窗口。

應用場合:將一些關鍵信息輸出到VUser運行狀態窗口,方便場景執行時查看。

舉例:在場景運行過程當中,出現了錯誤。根據錯誤窗口提示,該錯誤屬於VUser ID爲2的虛擬用戶,爲了方便將系統登陸用戶名與VUser ID對應起來,以方便問題定位。可使用如下代碼:

lr_vuser_status_message("Thelogin username is %s", lr_eval_string("{username}"));

場景執行時,可方便查看到VUserID與登陸用戶名的對應關係,以下圖:

 

 

注意點:

 

3.2.5.其它實用函數

3.2.5.1. lr_get_vuser_ip

功能:得到VUser的IP地址。

應用場合:在使用IP欺騙時,爲了驗證IP欺騙是否成功,可使用該函數。

舉例:在場景運行過程當中,將每個VUser的IP在VUser運行狀態窗口中顯示出來。

char *ip;

ip = lr_get_vuser_ip();

if (ip)

{

  lr_vuser_status_message("The IP addressis %s", ip);

}

注意點:爲了使IP欺騙成功,使用IP欺騙嚮導設置好IP後,還要將打開纔可。

3.2.5.2. lr_load_dll

功能:加載外部DLL。

應用場合:腳本須要使用外部DLL時,使用該函數加載DLL。

舉例:函數getDateTime(char * time,int seconds,char * resultTime)已封裝在timeutil.dll中,getDateTime的功能是根據傳入的日期字符串time(如2008-09-24 16:56:24),秒偏移量seconds,計算返回結果日期字符串resultTime,代碼以下:

int hours =atoi(lr_eval_string("hours"));

char acceptEndTime[20];

lr_load_dll("../timeutil.dll");

getDateTime(lr_eval_string("{acceptBeginTime}"),3600*hours,acceptEndTime);

注意點:該函數爲LoadRunner提供了調用外部接口的能力。

 

3.3.封裝,構建可重用腳本

3.3.1.簡單函數封裝

LoadRunner使用C語言做爲腳本,所以只要是合法的C代碼均可以在LoadRunner中運行。爲了提升腳本可讀性和腳本生產效率,有必要將性能測試腳本模塊化。

客服3.0工做流系統,查詢工單池是一個很常見的操做。咱們能夠把查詢工單池操做封裝爲一個queryTTPool函數,函數體以下,在腳本中,將全部的查詢工單池操做替換爲queryTTPool函數調用,提升了腳本的可讀性:

//查詢工單池

int queryTTPool(char* nodeType){

   lr_save_string(nodeType,"nodeType");

   lr_save_datetime("%Y-%m-%d 00:00",DATE_NOW-2*ONE_DAY, "acceptBeginTime");

   lr_save_datetime("%Y-%m-%d 23:59", DATE_NOW,"acceptEndTime");

   lr_start_transaction("WF_查詢工單池工單");

   web_submit_data("IWFController",

        "Action=http://{wf_sysurl}/IWFController",

        "Method=POST",

        "RecContentType=text/html",

         "Referer=http://{wf_sysurl}/iwflow/common/UnitQueryDealForm.jsp?pageNo=1",            "Snapshot=t32.inf",

        "Mode=HTML",

        ITEMDATA,

        "Name=ACTIONID","Value=UniteQueryDealAction", ENDITEM,

        "Name=pageNo", "Value=1", ENDITEM,

        "Name=sortType", "Value=", ENDITEM,

        "Name=sortField", "Value=", ENDITEM,

        "Name=reSortFlag", "Value=", ENDITEM,

        "Name=acceptPhone", "Value=", ENDITEM,

        "Name=serialNo", "Value=", ENDITEM,

        "Name=serialFlag", "Value=0", ENDITEM,

        "Name=serviceName", "Value=", ENDITEM,

        "Name=serviceID", "Value=", ENDITEM,

        "Name=acceptBeginTime","Value={acceptBeginTime}", ENDITEM,

        "Name= acceptEndTime ", "Value={acceptEndTime}",ENDITEM,

        "Name=urgentID", "Value=", ENDITEM,

        EXTRARES,

        "Url=/iwflow/image/kms-1_23.gif", ENDITEM,

        "Url=/iwflow/buttons/obtainProcess-2.gif", ENDITEM,

        LAST);

   lr_end_transaction("WF_查詢工單池工單",LR_AUTO);

}

 

3.3.2.DLL封裝

使用DLL有不少好處。高度重用的函數製做成DLL,方便腳本調用。將與IVR交互的消息函數封裝成DLL後,即可利用LoadRunner測試IVR性能。製做DLL能夠選擇VC或者MinGW Developer Studio等工具,至於DLL的製做細節,本文不做介紹,請參見相關指導書。

4   腳本調試

LoadRunner的VUser Generator自己的調試功能比較弱,只能設置斷點,沒法單步跟蹤。當腳本出現問題時,可使用lr_debug_message,lr_output_message,lr_eval_string等函數協助定位。

腳本錯誤大部分緣由都是向服務器發送的數據不對,所以還能夠利用HttpAnalyzer工具進行HTTP協議跟蹤,經過比較LoadRunner發送的數據和瀏覽器發送的數據,便能很快定位出問題根源。

相關文章
相關標籤/搜索