locustfile中的User類和HttpUser類


locustfile中的User類和HttpUser類

 

locustfile是什么?

locustfile是Locust性能測試工具的用戶腳本,描述了單個用戶的行為。

locustfile是個普通的Python模塊,如果寫作locustfile.py,那么路徑切換到文件所在目錄,直接執行命令就能運行:

$ locust

如果換個名字,那么只能通過-f參數指定文件名運行:

$ locust -f locust_files/my_locust_file.py

與一般Python模塊不同的是:locustfile必須至少定義一個類,且繼承自User類。

User類

User類表示性能測試的模擬用戶,Locust會在運行時創建User類的實例

wait_time屬性

設置等待時間,默認值不等待,立即執行。

Locust支持4種方式設置wait_time屬性

為了便於理解實際意義,我把源碼貼在了下面。

  • constant函數,常量,任務執行完畢等待X秒開始下一任務。

    def constant(wait_time):
        """ Returns a function that just returns the number specified by the wait_time argument Example:: class MyUser(User): wait_time = constant(3) """
        return lambda instance: wait_time
    
  • between函數,區間隨機值,任務執行完畢等待X-Y秒(中間隨機取值)開始下一任務。

    def between(min_wait, max_wait):
        """ Returns a function that will return a random number between min_wait and max_wait. Example:: class MyUser(User): # wait between 3.0 and 10.5 seconds after each task wait_time = between(3.0, 10.5) """
        return lambda instance: min_wait + random.random() * (max_wait - min_wait)
    
  • constant_pacing函數,自適應,若任務耗時超過該時間,則任務結束后立即執行下一任務;若任務耗時不超過該時間,則等待達到該時間后執行下一任務。

    def constant_pacing(wait_time):
        """ Returns a function that will track the run time of the tasks, and for each time it's called it will return a wait time that will try to make the total time between task execution equal to the time specified by the wait_time argument. In the following example the task will always be executed once every second, no matter the task execution time:: class MyUser(User): wait_time = constant_pacing(1) @task def my_task(self): time.sleep(random.random()) If a task execution exceeds the specified wait_time, the wait will be 0 before starting the next task. """
    
        def wait_time_func(self):
            if not hasattr(self, "_cp_last_run"):
                self._cp_last_wait_time = wait_time
                self._cp_last_run = time()
                return wait_time
            else:
                run_time = time() - self._cp_last_run - self._cp_last_wait_time
                self._cp_last_wait_time = max(0, wait_time - run_time)
                self._cp_last_run = time()
                return self._cp_last_wait_time
    
        return wait_time_func
    
  • 自定義wait_time方法,比如每次等待時間1秒2秒3秒遞增:

    class MyUser(User):
        last_wait_time = 0
    
        def wait_time(self):
            self.last_wait_time += 1
            return self.last_wait_time
    
        ...
    

weight屬性

設置創建類實例的權重,默認每個類創建相同數量的實例。

locustfile中可以有多個繼承了User類的類

命令行可以指定運行哪些類:

$ locust -f locust_file.py WebUser MobileUser

通過weight屬性可以讓類更大概率創建實例,比如:

class WebUser(User):
    weight = 3
    ...

class MobileUser(User):
    weight = 1
    ...

WebUser類比MobileUser類多三倍概率創建實例。

host屬性

設置URL前綴。

一般是在Locust的Web UI或者命令行,通過--host指定URL前綴。如果沒有通過--host指定,並且類中設置了host屬性,那么類的host屬性才會生效。

environment屬性

對用戶運行環境的引用。

比如在task方法中通過environment屬性終止運行:

self.environment.runner.quit()

注意,單機會終止所有運行,分布式只會終止單個worker節點。

on_start和on_stop方法

測試前初始化和測試后清理。

HttpUser類

開篇文章的示例腳本,沒有繼承User類,而是繼承了它的子類HttpUser:

image-20210507203533924

它比User類更常用,因為它添加了一個client屬性,用來發送HTTP請求

client屬性/HttpSession

HttpUser類的client屬性是HttpSession類的一個實例:

image-20210510100543452

HttpSession是requests.Session的子類,requests就是常用來做接口測試的那個requests庫:

image-20210510161237184

HttpSession沒有對requests.Session做什么改動,主要是傳遞請求結果給Locust,比如success/fail,response time,response length,name。

示例:

response = self.client.post("/login", {"username":"testuser", "password":"secret"})
print("Response status code:", response.status_code)
print("Response text:", response.text)
response = self.client.get("/my-profile")

由於requests.Session會暫存cookie,所以示例中登錄/login請求后可以繼續請求/my-profile

斷言響應結果

可以使用with語句和catch_response參數對響應結果進行斷言:

with self.client.get("/", catch_response=True) as response:
    if response.text == "Success":
        response.success()
    elif response.text != "Success":
        response.failure("Got wrong response")
    elif response.elapsed.total_seconds() > 0.5:
        response.failure("Request took too long")

或者直接拋出異常:

from locust.exception import RescheduleTask
...
with self.client.get("/does_not_exist/", catch_response=True) as response:
    if response.status_code == 404:
        raise RescheduleTask()

name參數

name參數用於把不同api按同一分組進行統計,比如:

for i in range(10):
    self.client.get("/blog?id=%i" % i, name="/blog?id=[id]")

會按/blog/?id=[id]統計1條數據,而不是分成10條數據。

HTTP代理

Locust默認設置了requests.Session的trust_env為False,不查找代理,以提高運行性能。如果需要可以設置locust_instance.client.trust_env為True。

示例代碼

請求REST API並斷言:

from json import JSONDecodeError
...
with self.client.post("/", json={"foo": 42, "bar": None}, catch_response=True) as response:
    try:
        if response.json()["greeting"] != "hello":
            response.failure("Did not get expected value in greeting")
    except JSONDecodeError:
        response.failure("Response could not be decoded as JSON")
    except KeyError:
        response.failure("Response did not contain expected key 'greeting'")

小結

locustfile是個普通Python模塊,必須繼承User類或其子類HttpUser等。本文對User類和HttpUser類的屬性和方法進行了介紹,使用它們可以編寫性能測試的用戶腳本。locustfile還有另外一個重要組成元素,@task

參考資料:

https://docs.locust.io/en/stable/writing-a-locustfile.html

https://blog.csdn.net/Orangesir/article/details/114914969



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM