学习笔记2——使用Locust创建http请求
本文写作时,使用当时最新版本的0.14.5,现在已更新到2.x,可能有误,请谨慎参考。
学习笔记1中主要是介绍了Locust的线程(虚拟用户)数的创建和执行策略,这里主要介绍用locust发起http请求
1.基本http请求
为了做各种场景测试,需要本地启动服务端模拟程序,先发一个无参的get请求和post请求(本地测试服务可以参照github搭建: https://github.com/wang153723482/http_world/tree/master/hello-springboot)
这里不再继承Locust这个类,而是继承了HttpLocust,这样在TaskSet的子类中,可以直接使用self.client这个属性
from locust import HttpLocust, TaskSet, task
from locust.wait_time import constant
class Task(TaskSet):
@task
def index(self):
self.client.get('/hello')
@task
def project(self):
self.client.post('/hello_post')
class MyHttpLocust(HttpLocust):
host = 'http://127.0.0.1:8080'
task_set = Task
wait_time = constant(1)
2.进阶
HttpLocust 有一个参数为client,在实例初始化的会创建一个session,用于访问http。session继承了requests.Session
HttpLocust继承了Locust
def __init__(self):
super(HttpLocust, self).__init__()
if self.host is None:
raise LocustError("You must specify the base host. Either in the host attribute in the Locust class, or on the command line using the --host option.")
session = HttpSession(base_url=self.host)
session.trust_env = self.trust_env
self.client = session
在TaskSet中,使用的client参数为self.locust.client,相关源码如下
@property
def client(self):
"""
Reference to the :py:attr:`client <locust.core.Locust.client>` attribute of the root
Locust instance.
"""
return self.locust.client
总之,就是locust可以用你保持session,通过下面的测试可以证实
from locust import HttpLocust, TaskSet, task
from locust.wait_time import constant
class Task(TaskSet):
@task
def hello_session(self):
self.client.get('/helloSession')
class MyHttpLocust(HttpLocust):
host = 'http://127.0.0.1:8080'
task_set = Task
wait_time = constant(1)
启动以后,可以在测试服务的控制台看到打印的sessionid,对于多次请求,sessionid是相同的值,但是对于不同的虚拟用户,sessionid是不同的值
locust -f http_request.py --no-web -c 3 -t 10 乌鸦:这条命令启动了3个虚拟用户,session_id会有3个不同的值
对于jmeter的HttpRequest来说,需要添加HTTP Cookie Manager才能保持默认情况下的http session
除了常用的get和post,其他的method也是支持的。
get, post, put, delete, head, patch and options
获取请求的返回结果
response = self.client.get("/about")
print("Response status code:", response.status_code)
print("Response content:", response.text)
提交键值对类型的参数
para = {"name": "zhangsan", "age": "88"}
response = self.client.post('/helloPara', para)
提交body参数
body = "asdf"
response = self.client.post('/hello_body',data=body)
设置http header
headers={'Content-Type':'application/json','myheader':'heiheihaha'}
response = self.client.post('/helloHeader',headers=headers)
3.断言
默认情况下,locust会认为response_code<400的为成功
使用 catch_response=True 可以捕获响应,然后进一步判断来断定成功还是失败
with self.client.get("/", catch_response=True) as response:
if response.content != b"Success":
response.failure("Got wrong response")
或者
with self.client.get("/does_not_exist/", catch_response=True) as response:
if response.status_code == 404:
response.success()
都是官网文档上的例子
其他的断言也类似,获取相应结果以后,解析结果,如果符合预期,则 执行 response.success(),否则执行 response.failure("error msg")
4.其他
官网文档上还有一个例子,重命名分组,对于locust的报表来说,是根据url进行分组的,使用name=''这个参数,可以将url不同的请求重新分组
乌鸦:在locust中,get请求传递键值对参数,只允许在url中拼接。如果是post可以将参数拼接在url中,也可以使用字典传值
# 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]")
安全模式
如果请求连接错误、超时或其他类似的错误,不会报异常退出,而是返回一个None,status_code返回0,并且会统计到错误报告中
下面这个错误就是在执行测试过程,手动关闭了目标服务器
POST /helloHeader:
'ConnectionError(MaxRetryError("HTTPConnectionPool(host='127.0.0.1',port=8080): Max retries exceeded with url: /helloHeader (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x04796A00>: Failed to establish a new connection: Errno 10061 由于目标计算机积极拒绝,无法连接。'))"))'
参考:
https://docs.locust.io/en/0.14.5/writing-a-locustfile.html#making-http-requests
https://docs.locust.io/en/0.14.5/api.html#httpsession-class
本文链接:http://bigerhead.com/2020/04/456.html 转载请注明出处。