api性能测试
Locust(俗称蝗虫)一个轻量级的开源压测工具,基本功能是用Python代码描述所有测试。不需要笨拙的UI或庞大的XML,只需简单的代码即可。
有一段时间没有弄性能测试了,最近需要压一压性能。有人用python去调用接口,然后用chales抓包,导出成har.然后将har转化成jmx,然后导入jemeter做压测。我觉得这样太麻烦。既然都是用python,为何不用python支持的locust.于是我将locust捡起来。网上的资料太少,太零散,而且好多都过时了,就是错的。现在写这个,就是做一个记录,少一些坑。
安装和使用pipinstalllocust
你看到的很多文档,都是老的,包早就改了。locust版本0.13之后已经废除了min_wait和max_wait的使用
min_wait=max_wait=
改为使用
wait_time=between(3,7)
而且这个类已经废弃了:HttpLocust换成:HttpUser一直报错,说没有task,后面发现,task_set=UserBehavior改成tasks=[UserBehavior]
增加断言
对于测试来说,每个自动化测试用例都应该有个断言判断,这样才能知道测试用例的成功/失败。
在Python+Locust中,通过with的方式来增加断言。具体脚本如下:
withself.client.post(url=url,data=params,timeout=10,catch_response=True)asresponse:ifresponse.status_code==:response.success()else:response.failure(Failed!)
注意:catch_response=True这个参数是必须要加的,否则在性能测试时,后台会一直报错,提示AttributeError:Responseobjecthasnoattributesuccess。
刚刚的样例中,是举例断言status_code是否等于,如果是,则返回成功,反之返回失败。
思考一下,我们运行性能测试的时候,需要哪些数据呢?step1准备脚本过程数据1.全局数据:exp(一批测试用户、一批测试商品)2.局部数据:a)用于接口动态入参,不用从上下文中获取(exp:时间戳)b)用于接口动态入参,需要从上下文中获取(exp:用户登录token或者cookie,订单ID)3.转换数据:exp(将明文密码转换为md5加密)setp2运行脚本过程中数据使用1.同一批数据:每个接口可重复取数2.同一批数据,每个接口取数不重复3.不同批数据:每个接口分别随机取值,不同批数据无关联关系,可随机匹配4.不同批数据:每个接口分别随机取值,不同批数据有对应关联关系二、关于上述场景数据参数化step1准备脚本过程中参数化处理1.全局数据:(对比jmeter调用text或者csv的文档方法)可以使用txt或者csv,在通过pyton中文件读取函数读取出来,有数据关联的建议每条以dictoflist形式进行存储使用python中list类型读取2.局部数据:a.上下文无关的动态参数,使用def函数返回值进行动态获取b.上下文相关的动态参数,使用taskset中类属性来进行获取并参数化
#txt中数据为1,2,3,4,5,6defget_txt_data():withopen("user.txt","r")asf:data=f.read()returndata
#列表形式数据s=[1,2,3,4,5,6]s1=[{"user_name":"张三","password":},{"user_name":"李四","password":},{"user_name":"王五","password":}]
#从上下文中取数据fromlocustimportLocust,TaskSet,task,betweenfromtimeimporttimefromuuidimportuuid1#返回当前时间戳defget_time_stamp():returnstr(int(time()))classMyTaskSet(TaskSet):#该函数不是task任务的,可以添加函数来进行获取token,方便任务来调用defget_login_token(self):returnuuid1()#使用类属性来进行参数传递token=None#TaskSet相当于下面所有task的大脑
task(1)#声明任务defmy_task(self):print("执行task1"+get_txt_data())MyTaskSet.token=uuid1()task(2)defmy_task_2(self):print("执行task2"+str(s[0])+str(MyTaskSet.token))classAppUser(Locust):weight=1#赋值权重weight=10默认为10task_set=MyTaskSetwait_time=between(1,2)host=""#域名hoststep2脚本运行过程中1.同一批数据或者多批数据:不同的taskset对应的user类中,使用相同的data数据不同的taskset对应的user类中,通过一个或者多个队列进行不重复取值(如果有关联关系的数据,可以重新一个队列,把对应关系用字典存入到队列)
#两个UserLocust重复调用一个list数据fromlocustimportHttpLocust,TaskSet,task,Locust,betweenimportqueue#frommultiprocessingimportQueues=[1,2,3,4,5,6]classMyTaskSet(TaskSet):
task()deftask_test1(self):print(queue_data_test1[0])classMyTaskSet2(TaskSet):task()deftask_test2(self):print(queue_data_test2[0])classUserLocust2(Locust):task_set=MyTaskSet2wait_time=between(3,10)queue_data_test2=sclassUserLocust(Locust):task_set=MyTaskSetwait_time=between(3,10)queue_data_test1=s#两个UserLocust调用同一个队列,数据取值不重复;(存在多批次不重复,可定义多个Queue()对象)fromlocustimportHttpLocust,TaskSet,task,Locust,betweenimportqueue#frommultiprocessingimportQueuedefqueue_data():queue_data=queue.Queue()#默认为先进先出该队列为task_set共享#queue.LifoQueue(),后进先出foriinrange(0,13):queue_data.put_nowait(i)#put_nowait不阻塞returnqueue_dataclassMyTaskSet(TaskSet):
task()deftask_test1(self):print(self.locust.queue_data_test1.get())classMyTaskSet2(TaskSet):task()deftask_test2(self):print(self.locust.queue_data_test2.get())classUserLocust2(Locust):weight=1task_set=MyTaskSet2wait_time=between(3,10)queue_data_test2=queue_data()#默认为先进先出该队列为task_set共享classUserLocust(Locust):weight=3task_set=MyTaskSetwait_time=between(3,10)queue_data_test1=queue_data()三.总结:上面只是用了样例描述了一下locust参数化的过程,基本上是用python的方法或者类调用来获取数据和传递参数选择使用Queue()对象来实现数据的不重复调用,从其他资料中也可以看到使用frommultiprocessingimportQueue的队列对象来控制多进程安全数据传递
如果我们写性能测试的case,如果一个一个写,得写半天。我自己写了个方法,自动生成脚本。首先得用
转载请注明:http://www.sonphie.com/jbzl/14164.html