Locust中有兩個非常重要的類:Locust類和Taskset類。了解這兩個類的使用對於Locust工具的使用是非常有必要的;
一、Locust類詳細說明
Locust類中的屬性有:
client屬性:
task_set: 指向一個TaskSet類,TaskSet類定義了用戶的任務信息,該屬性為必填;
max_wait/min_wait: 每個用戶執行兩個任務間隔時間的上下限(毫秒),具體數值在上下限中隨機取值,若不指定則默認間隔時間固定為1秒;
host:被測系統的host,當在終端中啟動locust時沒有指定--host參數時才會用到;
weight:同時運行多個Locust類時會用到,用於控制不同類型任務的執行權重。
在運行結果中發現job2是job1事件執行頻率的2倍;
如果希望讓某個 locust 類經常被執行,可以在這些類上設置一個 weight 屬性。
二、TaskSet類詳細說明
TaskSet類:實現了虛擬用戶所執行任務的調度算法,包括規划任務執行順序(schedule_task)、挑選下一個任務(execute_next_task)、執行任務(execute_task)、休眠等待(wait)、中斷控制(interrupt)等等。
在此基礎上,我們就可以在TaskSet子類中采用非常簡潔的方式來描述虛擬用戶的業務測試場景,對虛擬用戶的所有行為(任務)進行組織和描述,並可以對不同任務的權重進行配置。
在TaskSet子類中定義任務信息時,可以采取兩種方式,@task裝飾器和tasks屬性。
2.1 TaskSet類詳細說明--@task裝飾器
采用@task裝飾器定義任務:
代碼演示:
from locust import TaskSet, task
class UserBehavior(TaskSet):
@task(1)
def test_job1(self):
self.client.get('/job1')
@task(2)
def test_job2(self):
self.client.get('/job2')
@task(1)中的數字表示任務的執行頻率,數值越大表示執行的頻率越高
2.2 TaskSet類詳細說明--tasks屬性
采用tasks屬性定義任務:
代碼演示:
from locust import TaskSet
def test_job1(obj):
obj.client.get('/job1')
def test_job2(obj):
obj.client.get('/job2')
class UserBehavior(TaskSet):
tasks = {test_job1:1, test_job2:2}
說明:
tasks = {test_job1:1, test_job2:2}中,test_job1:1,test_job2:2表示事件執行的頻率,即test_job2的執行頻率是test_job1的兩倍
2.3 TaskSet類詳細說明--on_start函數
on_start函數是在Taskset子類中使用比較頻繁的函數。在正式執行測試前執行一次,主要用於完成一些初始化的工作。
例如,當測試某個搜索功能,而該搜索功能又要求必須為登錄態的時候,就可以先在on_start中進行登錄操作,HttpLocust使用到了requests.Session,因此后續所有任務執行過程中就都具有登錄態了
2.4 TaskSet類詳細說明--控制任務的執行順序
在TaskSequence類中,使用裝飾器@seq_task()可以用來控制任務的執行順序;里面的數值越小執行越靠前;
代碼舉例:
2.5 TaskSet類詳細說明--休眠等待(wait)
在Taskset類中,內置WAIT_TIME功能,它用於確定模擬用戶在執行任務之間將等待多長時間。Locust提供了一些內置的函數,返回一些常用的wait_time方法。
1、between(min,max)函數:用得比較多的函數
wait_time = between(3.0, 10.5):任務之間等待的時間是3到10.5秒之間的任意時間
2、constant(number)函數:
wait_time=constant(3):任務之間等待的時候是3秒鍾,且等待的時候不能超過任務運行的總時間,也就是在執行py文件時設置的時間
3、constant_pacing(number)函數:
wait_time=constant_pacing(3):所以任務每隔3秒執行,但是當到達運行的總時間時,任務運行結束;
2.6 TaskSet類詳細說明--TaskSets 嵌套
現實中有很多任務其實也是有嵌套結構的,比如用戶打開一個網頁首頁后,用戶可能會不喜歡這個網頁直接離開,或者喜歡就留下來,留下來的話,可以選擇看書、聽音樂、或者離開;
代碼舉例:
2.7 TaskSet類詳細說明--中斷控制(interrupt)
在有Taskset嵌套的情況下,執行子任務時, 通過 self.interrupt() 來終止子任務的執行, 來回到父任務類中執行, 否則子任務會一直執行;
在上一頁的案例中,在stay這個類中,對interrupt()方法的調用是非常重要的,這可以讓一個用戶跳出stay這個類有機會執行leave這個任務,否則他一旦進入stay任務就會一直在看書或者聽音樂而難以自拔。
三、Locust中實現參數化
在進行接口多用戶並發測試時,數據的重復使用可能會造成腳本的失敗,那么需要對用戶數據進行參數化來使腳本運行成功。
情景一
在此我們舉出百度搜索的例子,假設每個人搜索的內容是不相同的;那么我們可以假設把數據放到隊列中,然后從隊列中依次把數據取出來;
可以利用python中Queue隊列來進行處理;
Queue的種類:
Queue.Queue(maxsize=0):先進先出隊列
Queue.LifoQueue(maxsize=0):后進先出隊列
Queue.PriorityQueue(maxsize=0):構造一個優先隊列
參數maxsize是個整數,指明了隊列中能存放的數據個數的上限。一旦達到上限,插入會導致阻塞,直到隊列中的數據被消費掉。如果maxsize小於或者等於0,隊列大小沒有限制
Queue的基本方法:
Queue.Queue(maxsize=0) 如果maxsize小於1就表示隊列長度無限
Queue.LifoQueue(maxsize=0) 如果maxsize小於1就表示隊列長度無限
Queue.qsize() 返回隊列的大小
Queue.empty() 如果隊列為空,返回True,反之False
Queue.full() 如果隊列滿了,返回True,反之False
Queue.get([block[, timeout]]) 讀隊列,timeout等待時間
Queue.put(item, [block[, timeout]]) 寫隊列,timeout等待時間
Queue.queue.clear() 清空隊列
情景二
個別情況下測試數據可重復使用,因此我們可以把參數化數據定義為一個列表,在列表中取出數據;
四、Locust中實現關聯
在某些請求中,需要攜帶之前response中提取的參數,常見場景就是session_id。Python中可用通過re正則匹配,對於返回的html頁面,可用采用lxml庫來定位獲取需要的參數;
我們以Phpwind登陸的來進行舉例,在登陸的接口中需要把token參數傳給服務器,token的值由頁的接口返回;
方法一:使用正則表達式
方法二:采用lxml庫來定位獲取需要的參數
技術點:
1、導模塊:lxml模塊
2、etree.HTML() 從返回html頁面獲取html文件的dom結構
3、xpath() 獲取token的xpath路徑
五、Locust中實現斷言
在進行性能測試時,斷言是必須的。比如你在請求一個頁面時,就可以通過狀態來判斷返回的 HTTP 狀態碼是不是 200。
在locust中通過with self.client.get("url地址",catch_response=True) as response的形式;
通過 client.get() 方法發送請求,將整個請求的給 response, 通過 response.status_code 得請求響應的 HTTP 狀態碼。如果不為 200 則通過 response.failure('Failed!') 打印失敗!如果斷言失敗后會加到統計錯誤表中