事情的起因是这样的,最近接到了一个需求,要求对某些接口进行测试(笔者从事的是java开发相关工作,没搞过测试),最终的测试结果需生成一张报告,形式不限,要求美观。
当时我的想法是很美好的,首先捕获一只懂测试的同事,详细询问一下最终都需要测哪些参数,然后动动勤劳的小手,上网找套教程搞他一波,应该就差不多了,前期进展比较顺利,经过一番调研最终还是选择了jmeter来搞这个需求,刚开始上手不怎么顺利,主要原因是英语渣,官方文档就不要想了,只能可怜巴巴搜一搜有没有中文教程啥的,然而感觉还是云里雾里的,没找到什么比较全面的资料,最终求助了万能的B站。一边啃视频,一边钻研,终于把测试计划的流程搞定了。
然后和公司的前辈聊了一下,人家言辞之中隐约表达出最终的聚合报告美观程度的不认同,最终方案是尝试一下locust。
好吧,最终还是逃不过,无奈之下,又开始了上网查教程的漫漫长路。写下此文的目的主要有两点:
一、写一下我踩到的坑,希望可以帮助到其他人
二、记录一套模板,便于自己或者读者套用
在正文开始之前,首先要声明,由于作者本人没正经学过测试,对于python也知之甚少,本文所述,皆为昨天学习的知识以及个人理解,观点之中或许有错漏之处,各位看官自行分辨。
由于学习途径是通过网络,所以如果你发现我的代码某些内容,比如变量名什么的和网上其他文章重合,那么有可能该文章也是我在学习过程中的参考文章之一,至于为什么网上找到了模板自己还要再总结一份,这个文章末尾再说。
locust是什么?
一款测试工具
locust怎么用?
这个问题我们针对测试web后端的项目来说,首先,我们需要编写一部分python代码,这一部分代码就是告诉locust一些关键信息,比如,我们要测试的接口地址、请求参数、请求类型等等。
import time from locust import TaskSet from locust import HttpUser from locust import task class MyTask(TaskSet): def on_start(self): pass @task def create(self): rsp = self.client.post("/test/create", json={"id": 0, "state": 0}, catch_response=True, name='create') self.id = rsp.json()['id'] #转json,获取需要的值 time.sleep(5) if 2: rsp.success() else: rsp.failure('接口失败!') def on_stop(self): pass class UserRun(HttpUser): tasks = [MyTask]
第一套模板大家可以参考一下下,UserRun为启动类,告诉了locust实际要执行的任务的集合是哪个,在这里是我自定义的MyTask类。
on_start是最开始执行的方法,on_stop想必就不用多说了,至于中间的create方法,就是测试任务本身了,也就是locust在执行我们的测试计划时,需要执行的任务。
@task表示下面的方法是一个任务,self.client.post()表示我要发送一个post请求,几个参数依次为url、发送的json数据、第三个东西我也不太清楚啦,貌似是如果要告诉locust在什么情况下返回值算是成功,什么情况下是失败,就要加上这个参数、最后一个name属性会在聚合报告中体现出来,大家自己看效果就行了。
再下面的判断,永远为true哈哈,这个就是想试一下上述的第三个参数。
如何启动locust?
命令:locust -f 文件名.py --host=http://地址:端口
我只会这一种,好像还可以加入一些其他参数,有需要的观众老爷可以自行搜索一下。
那么问题来了,目前模板中只有一个任务,如果有多个任务怎么办呢?重要的是,如果任务之间有执行顺序需要怎么办呢?比如先访问一个接口,获取返回值,使用返回值访问另一个接口。
这种情况下,使用第一套模板就不太合适了,因为第一套模板的写法是并发执行,谁先谁后不好说(需要并发执行的观众老爷可以了解一下@task的属性,貌似可以调整任务执行到的概率)。
如何控制任务执行顺序?
先上模板
from locust import TaskSet from locust import SequentialTaskSet from locust import HttpUser from locust import taskclass boot(HttpUser): @task class MyTaskCase(SequentialTaskSet):# 继承这个类,任务按顺序执行 @task def create(self): self.id = rsp.json()['id'] # 得到返回值后,将下个任务需要用的值存入self中(多线程并发的情况会不会出问题我不知道哦,暂时没试过) @task def query(self): # 此处省略
看注释应该已经懂了吧,那就不多bilibili了
此处详细说一下,我遇到的一个大坑!
关于locust的聚合报告神秘失踪之谜,开始学习locust的时候,还一切安好,学到一半慕然回首,聚合报告不见了。
这就很烦,我就指着那东西呢,而且与此同时,折线图也变得非常奇怪,反正看着就不对劲。
为了让聚合报告成功显示,经历了一番漫长而艰辛的探索,最终发现如果你在发送请求的时候,加入了 catch_response=True那么就会出现这种情况,删掉就可以了。
那么原因是什么呢?我们可以根据它的名字猜测一下,捕获了响应结果,这可能就导致了响应结果没有给到聚合报告。
最后,说一下为什么我想自己总结两套模板,因为在昨天的学习过程中异常痛苦,并不是技术有多难使用,而是网上一些文章中的代码并不适用于我使用的locust版本,为了避免下次匆忙找模板,还是自己搞一份来得安心。