HttpUser class
HttpUser是最常用的用户。它添加了一个用于发出HTTP请求的客户机属性。
from locust import HttpUser, task, between
class MyUser(HttpUser):
wait_time = between(5, 15)
@task(4)
def index(self):
self.client.get("/")
@task(1)
def about(self):
self.client.get("/about/")
client attribute / HttpSession
client是HttpSession的一个实例。HttpSession是请求的子类/封装器。Session,所以它的特性有很好的文档记录,应该为许多人所熟悉。HttpSession添加的主要是向Locust报告请求结果(成功/失败,响应时间,响应长度,名称)。
它包含所有HTTP方法的方法:get, post, put,…
就像request,session,它保留了请求之间的cookie,所以它可以很容易地用于登录网站。
发一个POST请求,查看响应并隐式地重用我们为第二个请求获得的任何会话cookie
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")
HttpSession捕获任何请求。由Session抛出的异常(由连接错误、超时或类似的原因引起),而返回一个模型的Response对象,status_code设置为0,内容设置为None。
Validating responses
如果HTTP响应代码正常(<400),则认为请求成功,但是对响应进行一些额外的验证通常是有用的。
通过使用catch_response参数、with语句和对response.failure()的调用,可以将请求标记为失败。
with self.client.get("/", catch_response=True) as response:
if response.text != "Success":
response.failure("Got wrong response")
elif response.elapsed.total_seconds() > 0.5:
response.failure("Request took too long")
你也可以将请求标记为成功,即使响应代码很糟糕:
with self.client.get("/does_not_exist/", catch_response=True) as response:
if response.status_code == 404:
response.success()
您甚至可以通过抛出异常,然后在with块之外捕获它,从而完全避免记录请求。或者,您可以抛出一个蝗虫异常,如下面的示例,并让locust捕捉它。
from locust.exception import RescheduleTask
...
with self.client.get("/does_not_exist/", catch_response=True) as response:
if response.status_code == 404:
raise RescheduleTask()
REST/JSON APIs
下面是一个如何调用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'")
locust插件有一个现成的用于测试REST API的类:RestUser
Grouping requests
对于网站来说,其url包含某种动态参数的页面是很常见的。通常,将这些url分组到User的统计数据中是有意义的。这可以通过向HttpSession的不同请求方法传递名称参数来完成。
例子:
# Statistics for these requests will be grouped under: /blog/?id=[id]
for i in range(10):
self.client.get("/blog?id=%i" % i, name="/blog?id=[id]")
在某些情况下,可能无法向请求函数传递参数,例如与封装了请求会话的库/SDK交互时。另一种对请求进行分组的方法是设置client.request_name属性
# Statistics for these requests will be grouped under: /blog/?id=[id]
self.client.request_name="/blog?id=[id]"
for i in range(10):
self.client.get("/blog?id=%i" % i)
self.client.request_name=None
如果您想用最少的样板文件链接多个组,可以使用client.rename_request()上下文管理器。
@task
def multiple_groupings_example(self):
# Statistics for these requests will be grouped under: /blog/?id=[id]
with self.client.rename_request("/blog?id=[id]"):
for i in range(10):
self.client.get("/blog?id=%i" % i)
# Statistics for these requests will be grouped under: /article/?id=[id]
with self.client.rename_request("/article?id=[id]"):
for i in range(10):
self.client.get("/article?id=%i" % i)
HTTP Proxy 设置
为了提高性能,我们通过设置请求将请求配置为不在环境中查找HTTP代理设置。会话的trust_env属性为False。如果不想这样做,可以手动设置locust_instance.client。trust_env为True。要了解更多细节,请参阅请求文档。
Connection pooling
当每个HttpUser创建新的HttpSession时,每个用户实例都有自己的连接池。这类似于真实用户与web服务器的交互方式。
但是,如果希望在所有用户之间共享连接,则可以使用单个池管理器。为此,将pool_manager类属性设置为urllib3.PoolManager的一个实例。
from locust import HttpUser
from urllib3 import PoolManager
class MyUser(HttpUser):
# All users will be limited to 10 concurrent connections at most.
pool_manager = PoolManager(maxsize=10, block=True)