本文重點介紹JMeter工具在測試中地位以及其中一些難以理解或者手冊中含糊不清的感念,讀者可以通過本文了解這些概念,然后再根據自己的需要查閱JMeter中各個組件的具體用法來完成測試工作。
1. 簡介
JMeter是一個專門用于測試C/S應用的桌面測試軟件(并不適合于B/S結構,因為它很難模擬用戶在browser上的動作,如果需要測試B/S結構的應用,可以選擇Selenium這樣的工具),主要被用來完成功能測試,壓力測試 ,性能測試等工作。
JMeter與其它測試軟件相比的優勢如下:
它可以幫助測試者很方便地模擬出多用戶同時訪問服務器的環境(通過Thread Group),這樣可以檢測出很多平時在單線程環境下無法暴露出來的問題。
應用范圍很廣,幾乎所有你能想到的C/S應用它都能夠提供了相應的支。JMeter中自己定制了一些特定應用的測試方案,例如對HTTP Server的測試、對數據庫的測試、對Java程序的測試等。此外即使Jmeter沒有提供當前應用的測試環境,用戶也可以同昨BeanShell的方式自行定制。
提供了豐富的邏輯控制器,可以允許測試人員很方便地寫出一些相對復雜的測試邏輯。
提供完善的變量機制以及配置機制,幫助測試人員減輕編寫用例的負擔,減少重復工作。
提供了強大的監控組建,幫助測試人員很方便地得到測試結果統計信息。
JMeter的劣勢:
難以針對“正確性”進行測試。雖然JMeter提供了斷言機制,但是通常我們的測試在模擬多用戶操作,因此某個用戶發出一個請求后得到的響應是不可預測的(例如同時對一個數據庫表進行讀寫,雖然我們可以讓每個模擬用戶將寫入的信息存儲在某個公共區域,但仍然可能會有問題,因為數據庫寫入的時間和寫入公共區域的時間并不能保證同步),因此如果想通過JMeter驗證應用的正確性還是比較麻煩的。通常我們只是利用斷言來檢查一些較為簡單而又重要的信息,例如返回碼。
沒有很好的BeanShell測試機制。在JMeter中,BeanShell是非常重要的一部分,因為通常JMeter定制的測試方案多少與我們的應用有些出入,這時需要使用BeanShell來完成一些JMeter無法完成的工作。然而BeanShell也是需要保證正確性的,而JMeter并沒有對BeanShell的測試提供很好的支持。
通過以上的分析,可以發現JMeter更適合找出被測試系統在并發環境下存在的問題。
2. JMeter測試用例的基本結構
JMeter測試用例的基本結構是一個類似于Windows資源管理器的樹形結構,這個樹中的每一個節點都由一個元素來表示,因此一個完整的JMeter測試用例實際上是由一個個元素組成的,而測試的執行過程實際上是這些元素的執行過程。一般而言,JMeter會使用深度優先的方式遍歷這些元素,而對于同一層的元素,JMeter會自上至下地執行。
在JMeter中有很多種元素,而每種元素在樹型結構中都有特定的意義,為了方便理解,這里把這些元素從結構性質上分為三大類:
第一類是控制型元素,這類元素通常出現在樹型結構的枝節點,它們被用來控制其下第一層元素(注意,不是其下所有元素)的執行,例如控制他們的先后順序,或者執行哪個或者不執行哪個。通過這類元素我們可以很方便地動態控制測試用例的執行過程,這些元素類似于變成語言中的if-else、switch、while等邏輯控制語句。
第二類是動作型元素,這類元素是真正發起測試請求的元素,它們通常位于樹型結構的底層,每一個動作元素代表一次請求-響應的過程,他們的執行順序通常被控制型元素管理。
第三類是配置型元素,它們只能作為樹型結構中的葉子節點,被用于對其作用范圍內(作用范圍的規則如下:如果該配置元素在控制元素下,則其作用范圍為該控制元素下的所有子孫節點;如果該配置元素在動作元素下,則其作用范圍僅為這一個動作元素)的所有動作型元素產生一定的影響。這些影響根據具體元素種類而不同,例如改變元素的參數、延遲請求時間、在請求前后加入一些動作、監聽請求及其相應。此外,如果某個動作型元素被多個相同的配置型元素影響后,這些配置型元素的效果會進行Merge,Merge的規則依照元素的功能類型不同而不同(詳見第3節)。
3. JMeter中的元素
從功能上講,JMeter的元素分為八大類以及兩個特殊元素。這里從使用場合上對這些元素進行敘述,至于具體每個元素什么功能則需要查看JMeter的幫助(具體方法是點擊未知的元素,然后選擇Help菜單下的Help選項)。
Test Plan元素:控制型元素。只能存在于樹型結構的根節點。它代表了整個測試方案,測試人員可以在這里設置一些全局性的內容,例如全局變量(注意全局變量是Thread Local的,詳見第4節)、ClassPath配置(如果希望在Jmeter中調用自己的Java類需要在這里設置了)等。
Thread Group元素:控制型元素。只能存在于Test Plan元素之下。它代表了一組行為相似的用戶,通常我們把一類用戶的動作放在同一個Thread Group下,這樣可以模擬多這這樣的用戶了。在這里可以配置模擬用戶的個數(線程的個數)、循環次數、執行時間等。
Logic Controller:控制型元素。可以存在于Thread Group下任何位子。它用來完成控制其下元素的執行,JMeter提供了很多Logic Controller類型的元素,方便我們在測試中實現基本的邏輯。
Config Element: 配置型元素。這些元素被用來改變其作用范圍內所有動作元素的配置,利用該類元素可以減少很多測試用例編寫中的重復工作,例如可以讓一個HTTP Request Defaults元素來配置所有用例中HTTP請求的主機地址以及端口號,這樣無須在每個動作元素中都做這樣的配置了。當Merge發生時,如果某個域只有一個Config Element元素有值,則使用該值;如果某個域有多個Config Element元素有值,則使用離動作元素近的Config Element元素的值(在動作元素節點下的配置元素近)。
Timer: 配置型元素。如果希望控制請求發出的頻率,則應該使用Timer延遲這些請求。當Merge發生時,所有Timer的時間會相加。
Pre Processor: 配置型元素。用于根據一定條件修改所有被影響的動作元素。當Merge發生時,這些Pre Processor將被依次執行,離動作元素遠的先執行。
Post Processor: 同Pre Processor,只是發生在動作元素之后,用于從響應中提取需要的信息。
Assertions: 配置型元素。用于對其影響范圍內的動作元素的結果進行斷言,例如可以斷言一些HTTP請求的返回碼,如果不通過則系統會記錄本次錯誤。Merge發生時,所有的Assertion都會被判斷。
Listener: 配置型元素。用于監聽其影響范圍內所有動作元素,測試結果數據主要由該類元素產生,因此他們非常有用。Merge發生時,所有的Listener監控動作都會被執行。
Sampler: 動作型元素。代表一次請求-響應的過程,他們是測試用例中動作的發起者,是測試用例的主要元素。JMeter根據不同的應用預制了很多種動作元素,如果用戶覺得仍然不夠用甚至可以用BeanShell Sampler寫自己的動作。
4. JMeter中的變量
有的時候我們希望發送成千上萬個隨機的請求,或者希望本次請求的內容依賴于前幾次的請求,那么需要使用JMeter中的變量(注意,是Variable不是Property),這樣可以用變量來配置每一個請求,這樣可以讓同一個Sampler每次都能發出不同的請求。
使用變量時,首先必須注意的是,JMeter中的變量是線程獨立(Thread Local)的,也是說雖然我們定義了n個變量,但是在每個線程中都有這n個變量的鏡像,他們之間相互獨立,互不干擾。
當我們希使用變量的時候,首先需要創建所需的變量。在JMeter中創建變量的方式很多,一種途徑是通過Test Plan定義全局變量(用于所有的Thread Group,它也是線程獨立的),也可以通過Config Element中的User Defined Element來定義不同線程組的局部變量(注意,User Defined Element中定義的變量是用于整個線程組的,無論將這個元素放在哪里都會被應用于整個線程組,這是一個比較特殊的配置型元素),此外當我們在應用中對某個沒有創建的變量賦值(后面會講到賦值)時也會創建該變量。實際上JMeter的源碼中是使用Map來實現變量的,因此這些性質也不難理解。
當我們希望在某個地方引用一個變量的時候,可以通過${變量名}的語法來獲取變量的值。注意,如果這個變量沒有被定義,則這個式子會被當作普通的字符串。
修改某個變量值的方法有很多,可以通過BeanShell來修改,也可以通過JMeter中一些特定的元素來修改(例如CSV Date Config Element),還可以使用JMeter函數來定義修改某個變量(具體如何做,見后面的小節)。