LoadRunner脚本篇
LoadRunner腳本篇
?
關(guān)? 鍵? 詞:LoadRunner 性能測試腳本
摘?? ?? 要:編寫一個準(zhǔn)確無誤的腳本對性能測試有至關(guān)重要的意義。本文介紹LoadRunner的HTTP協(xié)議測試腳本編寫,總結(jié)腳本編寫經(jīng)驗
?
1?? 概述
腳本錄制編寫是性能測試的一個重要環(huán)節(jié)。在性能測試過程中,虛擬用戶模擬真實用戶使用被測系統(tǒng),這個“模擬”的過程正是通過性能測試腳本來實現(xiàn)的。因此,編寫一個準(zhǔn)確無誤的腳本對性能測試有至關(guān)重要的意義。完成性能測試腳本包括兩個步驟:腳本錄制和腳本編寫,本文重點關(guān)注腳本編寫。
2?? 腳本錄制
2.1.錄制方式
HTTP協(xié)議腳本錄制可選兩種方式:基于HTML和基于URL。選擇哪種錄制方式的原則如下:基于瀏覽器的HTTP應(yīng)用系統(tǒng)選擇HTML,基于其他方式的HTTP應(yīng)用系統(tǒng)選擇URL。
2.2.錄制注意點
取消錄制期間自動關(guān)聯(lián)功能;
如果部分測試腳本出現(xiàn)問題,需要重新錄制,可以只錄制存在問題的片斷腳本,方法是不選中錄制啟動對話框中的Record the application startup。
3?? 腳本編寫
3.1.常用技術(shù)
LoadRunner性能測試腳本編寫常用的技術(shù)包括參數(shù)化,關(guān)聯(lián),邏輯控制和腳本模塊化。
3.1.1.參數(shù)化
參數(shù)化就是將腳本中的常量轉(zhuǎn)化為變量的過程。通過錄制生成的腳本所有的數(shù)據(jù)都是常量,為了達(dá)到向服務(wù)器發(fā)送的數(shù)據(jù)多樣化的目的,需要將一些數(shù)據(jù)常量轉(zhuǎn)化為變量。
3.1.2.關(guān)聯(lián)
關(guān)聯(lián)就是查找動態(tài)數(shù)據(jù),并把查詢到的數(shù)據(jù)以參數(shù)的形式保存起來。在B/S或者C/S系統(tǒng)中,服務(wù)器返回給客戶端的數(shù)據(jù)有些是動態(tài)改變的,例如客服系統(tǒng)的人工來話流水號和工作流系統(tǒng)的工單流水號。當(dāng)打開工單生成頁面后,工單流水號已經(jīng)從服務(wù)器端獲取到了,而在提交工單步驟,需要將該流水號返回給服務(wù)器。因此,在提交工單之前,在腳本中必須獲得流水號。獲得流水號的方法就是關(guān)聯(lián)。
使用關(guān)聯(lián)功能動態(tài)保存的參數(shù)跟直接通過參數(shù)化生成的參數(shù)是一致的。唯一不同的是,通過參數(shù)化生成的參數(shù)在腳本中可以高亮顯示。
3.1.3.邏輯控制
業(yè)務(wù)系統(tǒng)在實際應(yīng)用中,業(yè)務(wù)操作步驟間往往存在邏輯。比如,客服3.0工作流系統(tǒng),業(yè)務(wù)代表處理工單,如果待辦區(qū)沒有工單等待處理,則先從工單池中提取工單到待辦區(qū),然后進(jìn)行處理,并且需要優(yōu)先處理超時或即將超時的工單。在工單處理的性能測試腳本中,也必須遵從這種業(yè)務(wù)邏輯。
LoadRunner性能測試腳本采用C語言,因此腳本邏輯控制同C語言一致,使用if,switch,while/for/do控制結(jié)構(gòu)。
3.1.4.腳本模塊化
腳本模塊化的目的是:提高腳本可讀性、可重用性和腳本生產(chǎn)效率。腳本模塊化的本質(zhì)是抽取函數(shù),一些很通用的函數(shù)甚至可以封裝為DLL。模塊化性能測試腳本的思想跟自動化測試的ActionWord有相似之處。
例如:客服3.0系統(tǒng)的登錄功能,無論是工作流、知識庫、公告便簽還是培訓(xùn)考試,它們都使用相同的登錄頁面。我們可以把登錄腳本抽取為一個函數(shù)csp_login(char *staffno,char * password),需要登錄操作時,不需要錄制和拷貝腳本,只要調(diào)用這個函數(shù)就可以了。
注意:并不是所有的腳本代碼塊都需要做模塊化處理,只有那些穩(wěn)定不變、并且經(jīng)常用到的代碼塊才需要做模塊化處理。不做得不償失的事。
3.2.典型函數(shù)
LoadRunner中,常用的函數(shù)有很多,這里只介紹編寫性能測試腳本過程中那些必然用到的函數(shù)。本文重點關(guān)注這些典型函數(shù)的應(yīng)用場合及注意點,至于函數(shù)詳細(xì)使用說明請參見LoadRunner幫助文檔。
3.2.1.事務(wù)相關(guān)
3.2.1.1. lr_start_transaction/lr_end_transaction
功能:事務(wù)開始/結(jié)束標(biāo)記。
應(yīng)用場合:需要統(tǒng)計某一段代碼塊執(zhí)行所需要的時間,這兩個函數(shù)需要成對使用。
舉例:工作流系統(tǒng)性能測試中有一個需求,300人在線,提交工單操作平均響應(yīng)時間在3秒以內(nèi),則需要在提交工單請求步驟之前插入lr_start_transaction,提交工單請求步驟之后插入lr_end_transaction。
注意點:這兩個函數(shù)只是標(biāo)記函數(shù),用于標(biāo)記事務(wù)開始/結(jié)束,因此可以嵌套使用,即事務(wù)中還可以包含子事務(wù)。
?
3.2.1.2. lr_think_time
功能:模擬思考時間,即等待時間。
應(yīng)用場合:在線用戶測試,為了讓每一個虛擬用戶模擬一個真實用戶的行為,即讓一個虛擬用戶對系統(tǒng)產(chǎn)生的壓力跟真實用戶相當(dāng),就必須使用這個函數(shù)。這是因為,用戶在使用系統(tǒng)的過程中,從一個操作轉(zhuǎn)換到另一個操作,是需要時間的,這個時間就是思考時間。
舉例:客服3.0工作流系統(tǒng)在線用戶測試。對于工單查詢操作,輸入查詢條件后提交查詢,從輸入查詢條件至提交查詢的時間間隔就是思考時間。因為LoadRunner無法模擬鍵盤輸入的過程,它只能模擬鍵盤輸入的等待時間,此時需要在提交查詢的那個動作前插入lr_think_time函數(shù)。
注意點:在錄制腳本中,原子事務(wù)內(nèi)不要包含lr_think_time函數(shù),否則該思考時間將被統(tǒng)計到事務(wù)響應(yīng)時間中,造成結(jié)果不準(zhǔn)確。另外lr_think_time是否啟作用,可通過runtime-seting進(jìn)行設(shè)置。
注:原子事務(wù)指那些不能再分割為更小事務(wù)的事務(wù),它經(jīng)常指一個單一的業(yè)務(wù)操作,通常表現(xiàn)為一個URL請求。
?
3.2.1.3. lr_rendezvous
功能:在Vuser腳本中設(shè)置集合點。
應(yīng)用場合:并發(fā)測試。
舉例:客服3.0培訓(xùn)考試系統(tǒng),100人同時打開同一份試卷。則需要在打開試卷的語句前插入lr_rendezvous函數(shù),并在場景中設(shè)置集合點策略。
注意點:非并發(fā)測試,例如在測試系統(tǒng)的處理能力時,最好不要設(shè)置集合點,因為一旦設(shè)置了集合點,將導(dǎo)致一些VUser處于等待狀態(tài),在這等待過程中服務(wù)器將是空閑的,這將導(dǎo)致不能準(zhǔn)確的測試出服務(wù)器的真實性能水平。集合點更多用于發(fā)現(xiàn)系統(tǒng)的并發(fā)問題。
?
3.2.2.參數(shù)化/關(guān)聯(lián)
3.2.2.1.lr_save_string/lr_save_int
功能:將某一字符串/整型保存為參數(shù)。
應(yīng)用場合:有些變量的值通過C語言生成,之后在測試腳本中要使用這些變量。
舉例:客服3.0業(yè)務(wù)配置臺系統(tǒng)增加業(yè)務(wù)代表操作,業(yè)務(wù)代表的工號和姓名使用C語言函數(shù)生成。工號和姓名分別保存在staff_no和staff_name變量中,則在腳本中可以使用lr_save_int(staff_no,"staffno"),lr_save_string(staff_name, "stafffname")將工號和姓名參數(shù)化。
注意點:無。
?
3.2.2.2.web_reg_save_param
功能:在服務(wù)器返回的文本中查找一個或者多個字符串,并將搜索到的字符串值保存在參數(shù)中。
應(yīng)用場合:在B/S或者C/S系統(tǒng)中,服務(wù)器返回給客戶端的數(shù)據(jù)有些是動態(tài)改變的,在腳本的下一個步驟中,需要使用該動態(tài)數(shù)據(jù)。這時,就需要使用關(guān)聯(lián)獲得該動態(tài)數(shù)據(jù)。
舉例:客服3.0工作流系統(tǒng),工單辦理每次都從待辦區(qū)中打開第一條工單,為打開第一條工單,需要獲取第一條工單的完整URL(包括URL中的parameter及其值),而每一次進(jìn)入待辦區(qū),第一條工單有可能是不一樣的。為獲取第一條工單的URL,將打開工單的URL做關(guān)聯(lián)。已知打開待辦區(qū)操作獲得的HTML有如下片斷:
<a href="#"οnclick="javascript:openseviceforprocess('/iwflow/FindJspID.jsp?serialNo=2008092200000033&serviceID=0099&nodeID=140004&dealID=2008092200000056&hisFlag=0&skillID=020401&dealSkillID=020101&dealStaff=1200','false');">
可在打開待辦區(qū)的操作前插入如下語句:
web_reg_save_param("tt_url", "LB=javascript:openseviceforprocess('","RB=','false')", "Ord=1","IgnoreRedirections=Yes", "Search=Body","RelFrameId=1", LAST );
運(yùn)行腳本后,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協(xié)議中只能識別HTML文檔,因此關(guān)聯(lián)的依據(jù)是HTML源碼,而不是經(jīng)過瀏覽器解析后的可視化文本。這一點很重要。
(2)關(guān)聯(lián)還能將多個匹配的參數(shù)保存在數(shù)組中,方法是指定ORD的屬性值為ALL,之后通過“{參數(shù)名_1}”, “{參數(shù)名_2}”, “{參數(shù)名_3}”格式可獲得數(shù)組元素的值。
(3)該函數(shù)有一個屬性NOTFOUND,默認(rèn)值為ERROR,也就是說,如果找不到要查找的數(shù)據(jù),將報出錯誤,在必要的時候,例如腳本邏輯控制需要,可以將NOTFOUND的屬性值設(shè)為WARNING,這樣LoadRunner將不產(chǎn)生錯誤。
?
3.2.2.3.lr_save_searched_string
功能:在某一個字符緩沖區(qū)中搜索指定的字符串,并將搜到的字符串保存在參數(shù)中。
應(yīng)用場合:可配合LoadRunner的關(guān)聯(lián)功能,靈活獲取服務(wù)器端返回的數(shù)據(jù)。
舉例:客服3.0工作流系統(tǒng),工單處理每次都從待辦區(qū)中打開第一條工單,打開工單的URL已經(jīng)通過關(guān)聯(lián)保存在tt_url參數(shù)中,在工單處理提交時,需要使用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
可使用以下函數(shù)保存serviceNo,serviceID,nodeID,dealID的值。
//保存serialNo,serviceID,nodeID,dealID參數(shù)
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
功能:將時間保存為參數(shù)。
應(yīng)用場合:應(yīng)用系統(tǒng)需要把時間數(shù)據(jù)提交給服務(wù)器端。
舉例:客服3.0工作流系統(tǒng)活動工單查詢,默認(rèn)查詢從當(dāng)天開始的最近三天工單。 則查詢的開始時間和結(jié)束時間可用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
功能:將當(dāng)前時間戳保存為參數(shù)。
應(yīng)用場合:應(yīng)用系統(tǒng)需要把時間戳提交給服務(wù)器端。
舉例:多媒體坐席客戶端,在向MClient提交信息時,需要附帶客戶端的時間戳,則可以使用該函數(shù)獲取當(dāng)前時間戳。
注意點:與lr_save_datetime不同的是,本函數(shù)保存的是時間戳,而lr_save_datetime保存的是日期和時間。
?
3.2.2.6.lr_eval_string
功能:將某一字符串中包含的所有參數(shù)替換為真實值,并返回替換后的字符串。
應(yīng)用場合:欲查看某一參數(shù)的值,可使用該函數(shù)。
舉例:客服3.0工作流系統(tǒng),生成工單時打開工單頁面準(zhǔn)備工單提交,提交之前想查看已通過關(guān)聯(lián)保存的serialNo參數(shù)的值。方法如下:
lr_output_message(lr_eval_string("TheserialNo is {serialNo}"));
注意點:如果不存在該參數(shù),將把“{參數(shù)名}”當(dāng)作普通字符串輸出。如本例,如果不存在serialNo參數(shù),則輸出:The serialNo is {serialNo}。
?
3.2.3.驗證點
3.2.3.1.web_reg_find
功能:在HTML文檔中查找指定的字符串。
應(yīng)用場合:該函數(shù)是檢查點函數(shù),在腳本中需要插入檢查點的地方使用。
舉例:客服3.0工作流系統(tǒng),提交工單生成后,需要驗證工單是否提交成功。則可根據(jù)頁面提示“工單生成成功”進(jìn)行驗證。在提交生成工單步驟前插入:
web_reg_find("Text=工單生成成功",LAST);
注意點:該函數(shù)是注冊型參數(shù),需要在請求服務(wù)器數(shù)據(jù)步驟之前插入該函數(shù)。與該函數(shù)功能類似的函數(shù)是web_find,但是web_find只對HTML方式的腳本起作用,對URL方式腳本則不起作用,而且web_find函數(shù)效率低下,已被廢棄。
?
3.2.3.2. web_image_check
功能:判斷某一個圖片是否存在HTML頁面中。
應(yīng)用場合:同web_reg_find函數(shù)一樣,該函數(shù)也是檢查點函數(shù),在腳本中需要插入檢查點的地方使用。
舉例:客服3.0培訓(xùn)考試系統(tǒng)并發(fā)測試,50個人同時打開試卷,為了驗證打開試卷成功,根據(jù)試卷中的圖片public/images/onexam.gif進(jìn)行驗證:
web_image_check("web_image_check","Src=public/images/onexam.gif",LAST);
注意點:要使該函數(shù)生效,需要在runtime-seting中將打開。與web_reg_find不一樣的是,該函數(shù)不是注冊型函數(shù),因此需要在請求返回步驟之后插入該函數(shù)。上文提過,LoadRunner只能識別文本,因此web_image_check函數(shù)其本質(zhì)仍然是文本驗證,完全可以用web_reg_find替代,而且強(qiáng)烈推薦使用web_reg_find作為檢查點函數(shù)。
?
3.2.4.日志輸出
3.2.4.1. lr_output_message
功能:將VUser的消息打印到日志文件和輸出窗口中,打印的消息帶有腳本行信息。
應(yīng)用場合:方便查看運(yùn)行信息,輔助問題定位。
舉例:客服3.0系統(tǒng),登錄工號已經(jīng)參數(shù)化,調(diào)試腳本時將當(dāng)前的登錄工號輸出到Replay Log窗口中。代碼如下:
lr_output_message("Thestaffno is %s",lr_eval_string("{staffno}"));
注意點:與該函數(shù)具有類似功能的還有:lr_debug_message,lr_log_message lr_message,lr_error_message它們之間的不同之處這里不作詳細(xì)介紹,請參見LoadRunner幫助文檔。
?
3.2.4.2. lr_vuser_status_message
功能:將VUser的消息輸出到場景運(yùn)行的VUser狀態(tài)窗口。
應(yīng)用場合:將一些關(guān)鍵信息輸出到VUser運(yùn)行狀態(tài)窗口,方便場景執(zhí)行時查看。
舉例:在場景運(yùn)行過程中,出現(xiàn)了錯誤。根據(jù)錯誤窗口提示,該錯誤屬于VUser ID為2的虛擬用戶,為了方便將系統(tǒng)登錄用戶名與VUser ID對應(yīng)起來,以方便問題定位。可以使用以下代碼:
lr_vuser_status_message("Thelogin username is %s", lr_eval_string("{username}"));
場景執(zhí)行時,可方便查看到VUserID與登錄用戶名的對應(yīng)關(guān)系,如下圖:
?
?
注意點:無
?
3.2.5.其它實用函數(shù)
3.2.5.1. lr_get_vuser_ip
功能:獲得VUser的IP地址。
應(yīng)用場合:在使用IP欺騙時,為了驗證IP欺騙是否成功,可以使用該函數(shù)。
舉例:在場景運(yùn)行過程中,將每一個VUser的IP在VUser運(yùn)行狀態(tài)窗口中顯示出來。
char *ip;
ip = lr_get_vuser_ip();
if (ip)
{
? lr_vuser_status_message("The IP addressis %s", ip);
}
注意點:為了使IP欺騙成功,使用IP欺騙向?qū)гO(shè)置好IP后,還要將打開才可。
3.2.5.2. lr_load_dll
功能:加載外部DLL。
應(yīng)用場合:腳本需要使用外部DLL時,使用該函數(shù)加載DLL。
舉例:函數(shù)getDateTime(char * time,int seconds,char * resultTime)已封裝在timeutil.dll中,getDateTime的功能是根據(jù)傳入的日期字符串time(如2008-09-24 16:56:24),秒偏移量seconds,計算返回結(jié)果日期字符串resultTime,代碼如下:
int hours =atoi(lr_eval_string("hours"));
char acceptEndTime[20];
lr_load_dll("../timeutil.dll");
getDateTime(lr_eval_string("{acceptBeginTime}"),3600*hours,acceptEndTime);
注意點:該函數(shù)為LoadRunner提供了調(diào)用外部接口的能力。
?
3.3.封裝,構(gòu)建可重用腳本
3.3.1.簡單函數(shù)封裝
LoadRunner使用C語言作為腳本,因此只要是合法的C代碼都可以在LoadRunner中運(yùn)行。為了提高腳本可讀性和腳本生產(chǎn)效率,有必要將性能測試腳本模塊化。
客服3.0工作流系統(tǒng),查詢工單池是一個很常見的操作。我們可以把查詢工單池操作封裝為一個queryTTPool函數(shù),函數(shù)體如下,在腳本中,將所有的查詢工單池操作替換為queryTTPool函數(shù)調(diào)用,提高了腳本的可讀性:
//查詢工單池
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有很多好處。高度重用的函數(shù)制作成DLL,方便腳本調(diào)用。將與IVR交互的消息函數(shù)封裝成DLL后,便可利用LoadRunner測試IVR性能。制作DLL可以選擇VC或者M(jìn)inGW Developer Studio等工具,至于DLL的制作細(xì)節(jié),本文不作介紹,請參見相關(guān)指導(dǎo)書。
4?? 腳本調(diào)試
LoadRunner的VUser Generator本身的調(diào)試功能比較弱,只能設(shè)置斷點,無法單步跟蹤。當(dāng)腳本出現(xiàn)問題時,可以使用lr_debug_message,lr_output_message,lr_eval_string等函數(shù)協(xié)助定位。
腳本錯誤大部分原因都是向服務(wù)器發(fā)送的數(shù)據(jù)不對,因此還可以利用HttpAnalyzer工具進(jìn)行HTTP協(xié)議跟蹤,通過比較LoadRunner發(fā)送的數(shù)據(jù)和瀏覽器發(fā)送的數(shù)據(jù),便能很快定位出問題根源。
轉(zhuǎn)載于:https://www.cnblogs.com/qmfsun/p/4323273.html
總結(jié)
以上是生活随笔為你收集整理的LoadRunner脚本篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Swift实战-小QQ(第2章):QQ侧
- 下一篇: 非mapreduce生成Hfile,然后