1. 程式人生 > >LoadRunner關聯詳解

LoadRunner關聯詳解

關聯是LoadRunner的精髓,可以說不會關聯就不會效能測試,在網上有很多關於關聯的文章和部落格,但是發現很多文章把做關聯時如何確定兩份指令碼中不同的值是否需要關聯,以及關聯函式插入的位置的確定都介紹的很模糊,我感覺這裡是重點,因為這個過程有兩次查詢日誌的操作,且這兩次的目的並不一樣,而且兩次複製的查詢內容也是不同的,初學者很容易搞暈。這裡網上很多教程介紹兩次都複製指令碼中的動態值去日誌中查詢,真心不明白。Replay log是回放日誌,指令碼經過回放後伺服器返回的唯一辨識碼已經改變,再次複製錄製時的指令碼中的辨識碼去查詢怎能找到?反正本人當初是被很多文章給誤解了。下面進入正題,我們用LoadRunner自帶的訂票系統做演示。

在做關聯之前我們先了解一下LoadRunner的工作原理,這樣更便於理解為什麼會做關聯。

當執行指令碼時,VuGen偽裝成瀏覽器,然後根據指令碼,把當初真的瀏覽器所說過的話,再對網站伺服器重新說一遍,VuGen企圖騙過伺服器,讓伺服器以為它就是當初的瀏覽器,然後把網站內容傳送給VuGen。
所以紀錄在指令碼中要跟伺服器所說的話,完全與當初錄製時所說的一樣,是寫死的(hard-coded)。這樣的作法在遇到有些比較聰明的伺服器時,還是會失效。這時就需要透過「關聯(correlation)」的做法來讓VuGen可以再次成功地騙過伺服器。

所謂的關聯(correlation)就是把指令碼中某些寫死的(hard-coded)資料,轉變成是擷取自伺服器所送的、動態的、每次都不一樣的資料。
舉一個常見的例子,伺服器在每個瀏覽器第一次跟它要資料時,都會在資料中夾帶一個唯一的辨識碼,接下來就會利用這個辨識碼來辨識跟它要資料的是不是同一個瀏覽器。一般稱這個辨識碼為Session ID。對於每個新的交易,伺服器都會產生新的Session ID給瀏覽器。這也就是為什麼執行指令碼會失敗的原因,因為VuGen還是用舊的Session ID向伺服器要資料,伺服器會發現這個Session ID是失效的或是它根本不認識這個Session ID,當然就不會傳送正確的網頁資料給VuGen了。


如上圖,當錄製指令碼時,瀏覽器送出網頁A的請求,伺服器將網頁A的內容傳送給瀏覽器,並且夾帶了一個ID=123的資料,當瀏覽器再送出網頁B的情求時,這時就要用ID=123的資料,伺服器才會認為這是合法的請求,並且把網頁B的內容送回給瀏覽器。
在執行指令碼時會發生什麼狀況?瀏覽器再送出網頁B的請求時,用的還是當初錄製的ID=123的資料,而不是用伺服器新給的ID=456,整個指令碼的執行就會失敗。請仔細去理解此圖內容,這裡真正明白下面內容就好理解了。

由於自動關聯很不靠譜,人還是比機器更智慧,所以我們只介紹手動關聯,手動關聯的執行步驟大致如下:
1、使用相同的業務流程與資料,錄製二份指令碼
2、找出兩份指令碼中不同的地方
3、確定指令碼中有差異的地方是否需要關聯
4、確定關聯函式的插入位置
5、使用web_reg_save_param函式手動建立關聯
6、引數化要關聯的動態值
7、回放指令碼驗證關聯是否成功

使用相同的業務流程與資料錄製二份指令碼

先錄製一份指令碼並存檔, 依照相同的操作步驟與資料錄製第二份指令碼並存盤。注意,所有的步驟和輸入的資料一定都要一樣,這樣才能找出由伺服器端產生的動態資料。有時候會遇到真的無法使用相同的輸入資料,那您也要記住您使用的輸入資料,到時才能判斷是您輸入的資料,還是變動的資料。

找出兩份指令碼中不同的地方


如上圖,選用文字對比工具將兩份指令碼進行對比 (也可以使用LoadRunner自帶的WinDiff進行對比)
逐一檢視二份指令碼中差異的部份,每一個差異都可能是需要做關聯的地方。選取差異的指令碼,然後複製。
在複製時,有時並不需要取整行指令碼,可能只會選取指令碼中的一部分。
注意:請忽略lr_thik_time的差異部份,因為lr_thik_time是用來模擬每個步驟之間使用者思考延遲的時間。

確定指令碼中差異的地方是否需要做關聯

如上圖,複製其中一份指令碼中不同的內容,然後在該指令碼對應的Generation Log中找這個值。將滑鼠游標點到Generation Log的第一行開頭,按下Ctrl+F,開啟【Find】視窗,貼上剛剛複製的指令碼,找出在Generation Log第一次出現的位置。
在Generation Log中找不到要找的資料,這時請先確認您找對了指令碼,畢竟現在開啟了二個幾乎一樣的指令碼,很容易弄錯。
在Generation Log中找到了要找的資料,這時要確認資料是從伺服器端傳送過來的。首先可以先檢查資料的標頭,從標頭的Response Body可以知道資料是從伺服器端傳送到client端的。假如此資料第一次出現是在Request Header中,則表示此資料是由client端產生,不需要做關聯,但是有可能需要做引數化(parameterized)。
您要找的標頭格式如下:
 ******* Response Body For Transaction With Id 13 ******

確定關聯函式的插入位置

在之前的步驟,我們已經在Execution Log中找到可能需要關聯的動態資料,複製動態值部分進行關聯就可以進行關聯了,但是我們的關聯函式應該插入到指令碼的什麼位置呢?所以我們要先找出使用web_reg_save_param函式的正確位置,所以我們要再重新執行一遍指令碼,而且這次會開啟所有的Log。 在VuGen中點選【Vuser】>【Run-Time Settings】>【General】>【Log】>勾選【Enable logging】、【Always sends messages】、【Extended log】以及【Extended log】下的所有選項,按下【OK】,然後就可以執行指令碼了。


如上圖,執行完指令碼之後,複製動態值所在行的其他指令碼內容(而不是動態值本身)在Repaly  Log中進行查詢。找到字串後,在字串前面會有Action.c(4):,這個4就是到時候要插入web_reg_save_param函式的位置,也就是要插入到指令碼的第4行。
為什麼關聯函式要插入到第4行?而不是動態值所在的那一行?
 因為web_reg_save_param函式為註冊函式,必須在動態值的前面,相當於先宣告,後作用。注意:並不是在動態值的前面就行了,一定得在該動態值所屬的請求前,如例子中應該在“web_url”前面,而不是第17行的“web_submit_data”之前,這裡需要好好理解一下。

使用Web_reg_save_param函式建立關聯

將游標定位在指令碼的第四行前(在日誌中我們查詢到的那一行雙擊也可自動跳轉到需要關聯的位置),右擊>Insert>New step...,在彈出的視窗中展開Services結點,選擇“Web_reg_save_param”,然後點選ok。

如上圖,在彈出的視窗中填寫的“UserSession”是自己隨意取的引數名,取名時儘量見名知意,左右邊界值為所要關聯的動態值在Genertion log中的左右邊界值,其他引數項均為可選項。
關聯函式中的各個引數意義
 ParamName:存放動態資料的引數名稱
 list of Attributes:其它屬性,包含 Notfound, LB, RB, RelFrameID, Search, Instance, SaveOffset,  以及 SaveLen。屬性值不分大小寫,例如 Search=all。
Notfound:指定當找不到要找的動態資料時該怎麼處置。
Notfound=error:當找不到動態資料時,發出一個錯誤訊息。假如沒設定此屬性,此為LoadRunner的預設值。
Notfound=warning:當找不到動態資料時,不發出錯誤訊息,只發出警告,指令碼也會繼續執行下去不會中斷。在對角本除錯時,可以使用此屬性值。
LB:動態資料的左邊界字串。此屬性質是必須要有的,而且區分大小寫。
RB:動態資料的右邊界字串。此屬性質是必須要有的,而且區分大小寫。
RelFrameID:相對於URL而言,欲搜尋的網頁的Frame。此屬性質可以是All或是數字,而且可有可無。
Search:搜尋的範圍。可以是Headers(只搜尋headers)、Body(只搜尋body部分,不搜尋header)、Noresource(只搜尋body部分,不搜尋header與resource)或是All(搜尋全部範圍,此為預設值)。此屬性質可有可無。
Instance:指明從第幾次出現的值開始才是要擷取的資料。此屬性質可有可無,預設值是1。假如值為All,則所有找到符合的資料會儲存在陣列中。
SaveOffset:當找到符合的動態資料時,從第幾個字元開始才開始儲存到引數中。此屬性不可為負數,其預設值為0。
SaveLen:從offset開始算起,到指定的長度內的字串,才儲存到引數中。此引數可有可無,預設值是-1,表示儲存到結尾整個字串。
關聯函式中的這些引數存在的目的主要是幫助使用者去確定需要關聯內容的唯一性,所以使用時應靈活運用,只有ParamName、LB、RB這三個引數是必須的,其他的都不是,但一般會再用上Notfound=error,這樣如果沒關聯到我們容易發現錯誤。

引數化要關聯的動態值

做完以上工作後點擊“ok”看到指令碼中已插入“Web_reg_save_param”函式,至此關聯工作還沒有完成,我們剛才設定了引數”usersession“,現在需要把我們要關聯的動態值引數化,且引數名要為”usersession“,這樣關聯函式才能識別出來要關聯哪些內容。(引數名是自己取的,它就是用來動態值的,就是一個變數,可以隨便去取,但是最好見名知意)

在指令碼中選中關聯的動態值,右鍵>Replace with a Parameter>將引數名改為usersession>OK.
 引數化後被引數的動態值部分變為usersession,且以粉紅色顯示。

回放指令碼驗證關聯是否成功

最後執行一下指令碼,並查看回放日誌,驗證關聯是否成功

注意:執行指令碼時也要開啟全部日誌,這樣我們可以在日誌中看到關聯函式的事件資訊(藍色字型),以確保關聯成功;如果指令碼中有以”cookie“開頭的報錯資訊,不用去處理,對測試無影響。

關於易混淆的兩個地方這裡再廢話幾句:

1、第一次是在Generation log日誌中查詢動態值,看動態值在日誌中的標頭是“response...”還是“request...”,來確定該動態值是否需要關聯
2、第二次是在Repaly log日誌中查詢動態值所在行(注意:查詢時複製的查詢內容並不是動態值,而是動態值所在行的其他指令碼內容,因為Repaly log日誌是回放指令碼時產生的,指令碼經過回放後,動態值已改變,再複製動態值查詢極有可能查詢不到),目的是看該行前面的Action(X),來確定關聯函式應該插入的位置,X代表行,X為幾,對應的關聯就應該插入到此行前面。切記:第一次查詢是確定動態值是否需要關聯,第二次查詢日誌是確定關聯函式應插入在什麼位置