一、前言:
本文適合初學者,包含很多細節,也作為自己的備忘。有不准確之處,歡迎指正。
二、准備:
1、以虛擬機中的Linux系統作為服務器,開啟bugfree服務。
2、以fiddler作為抓包工具,輔助腳本開發。
3、腳本流程:bugfree登錄--創建bug--解決bug。
三、實現過程:
3.1 腳本主體
創建空白腳本后,結構如下圖,壓力測試中一般我們將登錄單獨放在vuser_init中。這里為了整個流程更清晰,腳本全部寫在Action中。
值得注意的是,我們設置腳本迭代次數,只對Action部分生效,而vuser_init和vuser_end只會運行一次。
開始寫腳本前,我們對fiddler先進行一些過濾設置。
在瀏覽器進行bugfree登錄操作,fiddler抓取到結果,比較有用的信息是URL以及Headers項的請求類型(這里是POST)、參數列表。
如果參數中以及后文的檢查點文本中含有中文,需要設置loadrunner支持UTF-8編碼格式,將含有UTF-8的項改為“Yes”:
在已知請求類型為POST的前提下,執行Insert--new step--Submit Data。如果是GET請求,則需要插入Url函數。
寫入General信息:
寫入參數信息:
點擊確定后生成腳本。創建bug和解決bug與此類似,生成腳本如下:
web_submit_data("創建缺陷", "Action=http://192.168.232.132/bugfree/info/edit?type=bug&action=opened&product_id=1", "Method=POST", "TargetFrame=", "Referer=", "Mode=HTTP", ITEMDATA, "Name=BugInfoView[deleted_file_id]", "Value=", ENDITEM, "Name=BugInfoView[lock_version]", "Value=", ENDITEM, "Name=BugInfoView[product_id]", "Value=1", ENDITEM, "Name=isPageDirty", "Value=1", ENDITEM, "Name=templateTitle", "Value=", ENDITEM, "Name=BugInfoView[title]", "Value=mutest20170927{title}", ENDITEM, "Name=layer1_module", "Value=0", ENDITEM, "Name=BugInfoView[productmodule_id]", "Value=0", ENDITEM, "Name=BugInfoView[assign_to_name]", "Value=系統管理員", ENDITEM, "Name=BugInfoView[mail_to]", "Value=", ENDITEM, "Name=BugInfoView[severity]", "Value=1", ENDITEM, "Name=BugInfoView[priority]", "Value=1", ENDITEM, "Name=Custom[BugType]", "Value=代碼錯誤", ENDITEM, "Name=Custom[HowFound]", "Value=代碼檢查", ENDITEM, "Name=Custom[BugOS]", "Value=Linux", ENDITEM, "Name=Custom[BugBrowser]", "Value=Chrome", ENDITEM, "Name=Custom[OpenedBuild]", "Value=Mu", ENDITEM, "Name=Custom[ResolvedBuild]", "Value=", ENDITEM, "Name=Custom[BugSubStatus]", "Value=", ENDITEM, "Name=Custom[BugMachine]", "Value=", ENDITEM, "Name=Custom[BugKeyword]", "Value=", ENDITEM, "Name=BugInfoView[related_bug]", "Value=", ENDITEM, "Name=BugInfoView[related_case]", "Value=", ENDITEM, "Name=BugInfoView[related_result]", "Value=", ENDITEM, "Name=attachment_file[]", "Value=", ENDITEM, "Name=BugInfoView[action_note]", "Value=", ENDITEM, "Name=BugInfoView[repeat_step]", "Value=<br />", ENDITEM, LAST); web_submit_data("解決缺陷", "Action=http://192.168.232.132/bugfree/bug/1/resolved", "Method=POST", "TargetFrame=", "Referer=", "Mode=HTTP", ITEMDATA, "Name=BugInfoView[deleted_file_id]", "Value=", ENDITEM, "Name=BugInfoView[lock_version]", "Value=1", ENDITEM, "Name=BugInfoView[product_id]", "Value=1", ENDITEM, "Name=isPageDirty", "Value=1", ENDITEM, "Name=templateTitle", "Value=", ENDITEM, "Name=BugInfoView[title]", "Value=mutest20170927{title}", ENDITEM, "Name=layer1_module", "Value=0", ENDITEM, "Name=BugInfoView[productmodule_id]", "Value=0", ENDITEM, "Name=BugInfoView[assign_to_name]", "Value=系統管理員", ENDITEM, "Name=BugInfoView[mail_to]", "Value=", ENDITEM, "Name=BugInfoView[severity]", "Value=1", ENDITEM, "Name=BugInfoView[priority]", "Value=1", ENDITEM, "Name=Custom[BugType]", "Value=代碼錯誤", ENDITEM, "Name=Custom[HowFound]", "Value=代碼檢查", ENDITEM, "Name=Custom[BugOS]", "Value=全部", ENDITEM, "Name=Custom[BugBrowser]", "Value=Chrome", ENDITEM, "Name=Custom[OpenedBuild]", "Value=Mu", ENDITEM, "Name=Custom[ResolvedBuild]", "Value=Mu", ENDITEM, "Name=BugInfoView[solution]", "Value=By Design", ENDITEM, "Name=BugInfoView[duplicate_id]", "Value=", ENDITEM, "Name=Custom[BugSubStatus]", "Value=Hold", ENDITEM, "Name=Custom[BugMachine]", "Value=", ENDITEM, "Name=Custom[BugKeyword]", "Value=", ENDITEM, "Name=BugInfoView[related_bug]", "Value=", ENDITEM, "Name=BugInfoView[related_case]", "Value=", ENDITEM, "Name=BugInfoView[related_result]", "Value=", ENDITEM, "Name=attachment_file[]", "Value=", ENDITEM, "Name=BugInfoView[action_note]", "Value=", ENDITEM, "Name=BugInfoView[repeat_step]", "Value=<br />", ENDITEM, LAST);
至此,腳本主體完成。但這樣的腳本很顯然是不符合壓測要求的:
1、如果對登錄單獨壓測,因為登錄是查詢型請求,與修改型請求不同,我們在數據庫中無從校驗其成功率。所以設置登錄檢查點函數是必要的。
2、如果登錄用戶名不允許多IP同時登錄,那么對用戶名進行參數化是必要的。參數化的本質是應對數據庫對參數值進行的唯一性校驗。
3、觀察腳本,解決Bug步驟,其Bug ID是固定的,那么執行壓測時,我們就一直在對同一個Bug進行解決缺陷操作,這顯然是不合理的。我們需要將Bug ID和上一步創建Bug的Bug ID關聯起來。這樣,才能保證每次解決缺陷都是針對上一步剛剛創建的處於未解決狀態的Bug。
接下來,對腳本進行改進:
3.2 參數化
參數化設置的目的是應對數據庫對參數值的唯一性校驗。其設置方式如下:
3.1.1 參數化設置
打開Parameter List,點擊左下角的【New】,創建新的參數。
生成之后,右鍵選中待替換內容,選擇【Use Existing Parameter】:
或者,也可以直接選中待參數化內容,右鍵后選擇【Replace with a Parameter】,一次性進行創建參數和替換。
3.2.2 Mysql數據庫數據獲取
設置參數化之后,面臨的問題就是大量數據從何而來。利用存儲過程在數據庫中創建大量數據,然后參數化文件讀取這些數據,是個不錯的方法。
Next
Next
Next
Next
Next
Next
Next,寫入sql語句
數據已導入:
參數類型即Parameter type還可選擇其他類型,常用的如Date/Time,Rondom Nunmber(可用於注冊型請求的用戶名參數)等,遇到實際場景后補充。
3.3 檢查點設置
以登錄為例,只要我們提交了請求,即使不能成功登錄,服務器返回給我們的狀態碼依然是200,而loadrunner判斷請求是否成功的依據就是返回的狀態碼,所以在未加檢查點之前,我們無從判斷登錄業務是否成功。當然,非查詢類請求,可以去數據庫進行校驗。
因此我們需要加入檢查點來進行業務是否真正成功的校驗。檢查點的思想是,在請求響應內容中,查找特殊字段,例如登錄請求響應中的“歡迎”、“退出”等等字段。下面以Bug登錄為例,進行檢查點詳細解析。
首先,我們去分析登錄請求中,檢查點需要設置的文本內容。
HTTP/1.1 302 Found Date: Sun, 10 Dec 2017 10:07:38 GMT Server: Apache/2.4.7 (Unix) OpenSSL/1.0.1f PHP/5.5.9 mod_perl/2.0.8-dev Perl/v5.16.3 X-Powered-By: PHP/5.5.9 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Set-Cookie: PHPSESSID=a3dta30c68sb9l7fc9t4ancp03; path=/ Set-Cookie: language=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/ Set-Cookie: language=bece46be16477e1ab82f9d40a53074cb0a54e105s%3A5%3A%22zh_cn%22%3B; expires=Tue, 09-Jan-2018 10:07:39 GMT; Max-Age=2592000; path=/ Location: http://192.168.232.128/bugfree/index.php Content-Length: 0 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
在響應內容中,貌似沒有特殊字段。只有“302”值得注意,這個狀態碼表示請求發生重定向,對象已臨時移動。那么,也只有登錄成功之后,才能進行跳轉首頁的重定向。為了驗證該結論,我做一次失敗登錄。第二次失敗登錄與第一次成功登錄相比,缺少了后續跳轉首頁等請求。
再觀察其響應內容,狀態碼是200。至此,我們可以選定登錄檢查點函數的檢查文本為“302”。
HTTP/1.1 200 OK Date: Sun, 10 Dec 2017 11:07:03 GMT Server: Apache/2.4.7 (Unix) OpenSSL/1.0.1f PHP/5.5.9 mod_perl/2.0.8-dev Perl/v5.16.3 X-Powered-By: PHP/5.5.9 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 4039 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html
執行Insert--new step--web_reg_find,reg表示注冊型函數,這類函數作用於其下文第一個函數。
生成腳本如下:
web_reg_find("Fail=NotFound", "Search=All", "SaveCount=count", "Text=302", LAST); web_submit_data("login", "Action=http://192.168.232.128/bugfree/index.php/site/login", "Method=POST", "TargetFrame=", "Referer=", "Mode=HTTP", ITEMDATA, "Name=LoginForm[username]", "Value=admin", ENDITEM, "Name=LoginForm[password]", "Value=123456", ENDITEM, "Name=LoginForm[language]", "Value=zh_cn", ENDITEM, "Name=LoginForm[rememberMe]", "Value=0", ENDITEM, LAST);
運行腳本:
Action.c(10): Registered web_reg_find successful for "Text=302" (count=2) [MsgId: MMSG-26364] Action.c(10): web_submit_data("login") was successful, 76514 body bytes, 1898 header bytes, 14 chunking overhead bytes [MsgId: MMSG-26385]
回到腳本中,修改密碼為“1234567”,運行腳本進行反向驗證:
Action.c(10): Error -26366: "Text=302" not found for web_reg_find [MsgId: MERR-26366] Action.c(10): web_submit_data("login") highest severity level was "ERROR", 4041 body bytes, 465 header bytes [MsgId: MMSG-26388]
至此,檢查點設置成功。檢查點特殊文本內容的確定需要一點點自己的分析。
3.3 關聯設置
一、為什么要設置關聯,常見場景有以下兩個:
1、登錄請求中,含有formhash、sessionid等特殊參數,這些參數的值每次請求將發生更新,而腳本中如果將其固定,下次請求仍然提交上次使用的參數值,請求將會失敗。
2、創建缺陷生成Bug ID,解決缺陷請求依賴該Bug ID,請求參數中Bug ID的值需要隨着創建缺陷生成的Bug ID同步更新。
下面以Bugfree解決缺陷為例,講述如何設置關聯:
首先,在【創建缺陷】請求的響應中查找“57730”,該ID是我新創建的。
截取其中一段包含“57730”的字段:
location='/bugfree/index.php/bug/57730';</
執行Insert--new step--web_reg_save_param,其中BugID是參數名,具備一定意義即可,后續請求需要引用該參數名。
生成腳本如下:
web_reg_save_param("BugID", "LB=location='/bugfree/index.php/bug/", "RB=';</", "Search=All", LAST);
為了查看關聯參數捕捉情況,開啟擴展日志:
運行腳本,觀察Replay Log,關聯參數捕捉成功:
Action.c(23): Registering web_reg_save_param was successful [MsgId: MMSG-26390] Action.c(29): Notify: Saving Parameter "BugID = 57732".
關聯參數捕捉結束,接下來很簡單,傳遞捕獲的參數到后續請求中,將具體值替換成引用值即可:
再次運行腳本:
Action.c(23): Registering web_reg_save_param was successful [MsgId: MMSG-26390] Action.c(29): Notify: Saving Parameter "BugID = 57734". Action.c(29): web_submit_data("創建缺陷") was successful, 28553 body bytes, 412 header bytes, 25 chunking overhead bytes [MsgId: MMSG-26385] Action.c(65): Notify: Parameter Substitution: parameter "BugID" = "57734" Action.c(65): web_submit_data("解決缺陷") was successful, 30589 body bytes, 412 header bytes, 25 chunking overhead bytes [MsgId: MMSG-26385]
關聯基本應用到此為止,后續補充復雜的關聯應用,例如關聯數組。
3.4 腳本調試
腳本調試應遵循分步調試原則,可以采用【斷點設置】和【單步跟蹤】。更簡便的方法就是利用注釋,比如,先將【創建缺陷】、【解決缺陷】注釋,單獨放開【登錄】,對其進行調試,由上至下依次進行。
通過View--Test result可查看Html格式視圖,便於排查腳本中的錯誤。例如下圖,表明UTF-8未設置,導致中文參數值不被識別: