51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 720|回复: 0
打印 上一主题 下一主题

[原创] 如何掌握接口并发性能测试分析?

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-10-13 16:31:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 草帽路飞UU 于 2022-10-13 16:33 编辑

 1. 引言


  这篇是我3月份在公司内部做的技术分享内容,由于我在公司内部分享的内容较多,以及一些特殊性,我摘取了接口并发测试从设计思路整理→测试方案设计→设计分析→代码编写这套流程。

  因为我不管是在内部技术分享,还是对个人的培训中,都发现:很多人并不清楚接口并发测试的整体流程,或者说,并没有参与过整个流程。

  所以,我把这部分内容摘取出来,分享出来,就是为了能让大家在测试开发的道路上,越走越远!

  接下来,就开始今天的分享,来看看接口并发性能测试的是怎样的分析流程。

  2. 并发测试定义


  目的:

  是以并发为手段进行接口测试行为,通过测试行为发现接口在并发场景下导致的功能问题。

  类型:

  ①点层面上:同一时间做某件事;

  例:早上7:30 ,所有的学生都升国旗

  ②线层面上:一个时间做不同的事,但同时对服务器产生压力;

  例:一个时间点,有的学生跳皮筋,有的玩足球

  敲黑板:

  并发与性能:并发测试不等同于性能测试,性能测试也只是并发测试的一个小类。

  3. 并发测试分类


  1、功能并发测试:


  解析:要先进行测试单业务功能场景的并发测试,在进行混合业务功能场景的并发测试。

  目的:为验证系统功能是否符合需求规格说明书的要求;

  2、性能并发测试:



  解析:同时满足某些系统性能指标的前提下,让被测对象承担不同的工作量,以评估被测对象的最大处理能力及是否存在缺陷。

  目的:为验证系统性能指标是否符合需求规格说明书的要求;

  3、稳定性并发测试:



  解析:判断测试系统的长期稳定运行的能力。

  目的:为验证系统稳定性是否符合需求规格说明书的要求;

  4、异常性并发测试:



  解析:模拟系统在较差、异常资源配置下运行,以评估被测对象在资源不足的情况下的工作状态。

  目的:为验证系统的异常响应机制是否满足需求规格说明书的要求。

  4. 设计思路整理



  1、需求分析


  ①首先找到并发测试对象,了解需求测试的功能有哪些,可以按照业务功能整理,不必深入细节。

  ②其次描述测试对象的重要性,如要求严格质量的核心功能、高频使用功能、占用系统资源较多的功能等。

  ③最后进行测试对象拆分,比如购买商品可以拆分成:搜索商品、锁定库存、提交订单、发送支付指令、接受处理支付结果、业务流水、短信及站内信通知、VX推送结果等。

  2、环境需求分析



  明确重点测试对象,预先设置基础数据及大量历史数据、模拟真实环境。

  3、性能指标需求分析



  分析性能指标是否合理。

  可以从历史数据的这几个方面考虑:TPS、页面访问量、并发请求数等,从而来判断需求指标是否合理,安排优先级。

  5. 测试方案设计



  1、测试策略


  并发测试的准备工作:

  请求顺序、请求之间互相调用关系、数据流向、有没有调用外部系统等后,需要明确重点测试对象,

  预先设置基础数据及大量历史数据,模拟真实环境等。

  测试策略执行,一般涉及以下4个阶段:

  ①对于功能并发测试:要先进行测试单业务功能场景的并发测试,在进行混合业务功能场景的并发测试。

  ②对于性能并发测试:同时满足某些系统性能指标的前提下,让被测对象承担不同的工作量,以评估被测对象的最大处理能力及是否存在缺陷。

  ③对于稳定性并发测试:判断测试系统的长期稳定运行的能力。该策略强度较小,一般趋向于客户现场日常状态下的压力强度。

  ④对于异常性并发测试:模拟系统在较差、异常资源配置下运行,如人为降低系统工作环境所需要的的资源,网络带宽、系统内存、数据帧等,以评估在资源不足情况下的工作状态。

  总结



  不同的测试阶段,测试人员关注的测试目的也是不同。所以对测试人员来说,测试思想才是最重要,有了测试思想,才会有好的测试方案。

  2、测试方案



  以两轮测试为例:

  第一轮测试,以接口文档驱动测试,测试步骤及要点如下。

  ①编写接口测试代码:核对每个接口传入参数控制:长度限制、格式、必填项限制、正常值范围限制等。同时,确认报错提示信息是否准确、到位;

  ②异常数据测试:如渠道值设置负数、属性设置不存在、网络断开、数据库锁表等情况,检查数据是否出现异常;

  ③逐个接口进行并发事务测试:检查账户金额,用户流水、对账流水数据。核对数据的与用例调用结果是否一致;

  ④复合接口并发测试:将各种充值、交易类型的接口按照一定的顺序进行并发,校验账户收支金额、流水是否与用例调用结果是否一致。

  第二轮测试,以业务场景驱动测试,测试步骤及要点如下。

  ①统一动作并发:相同订单并发支付,并发退款;

  ②混合交易场景:秒杀抢购,集中退货、到货确认;

  ③绕过页面操作:通过抓包,抛送异常值进行交易测试。

  6. 指标分析



  1、整理并发需求


  需求内容:

  中午和晚上是订餐的高峰期,所以会有很大的并发订单量。为了保证订单成功率、响应速度等因素,我们要进队高峰期的订单量进行并发性能测试。

  性能指标需求:

  ① 打开速度<3s,订单提交成功<5s;

  ②订单成功率达到99.5%以上;

  ③在100个并发用户的高峰期,订单处理能力至少达到900TPS。

  2、提取性能指标



  以100个外卖订单为例,需要提取的并发指标:

  ①并发订单数


  ②成功订单数

  ③成功订单响应时间

  ④订单成功率

  ⑤成功订单的总响应时间

  ⑥成功订单的平均响应时间

  ⑦Tps

  3、性能指标分析



  ①并发订单数:即自定义的并发数,把并发100次,设置为10个线程,每个循环10次;

  ②成功订单数:就是获取响应值为成功的请求,先定义一个success_count ,初始值为0,如果成功的话执行+1;

  ③订单成功率:成功订单数/总的订单数成功;

  ④订单总响应时间:每个成功订单的响应时间之和,所以我们定义一个sum_time,初始值为0.00,然后把每次成功的响应时间加起来成功;

  ⑤订单平均响应时间:成功订单总响应时间/成功订单数;

  ⑥TPS:成功并发数/成功订单平均响应时间;

  ⑦订单响应时间:在请求之前,获取一次时间,在断言成功之后,再次获取一次时间,这样二者之差,就是订单的响应时间。

  7. 代码实战



  咱们还是老规矩,直接上代码,在代码中做分析:

# -*- coding: utf-8 -*-

"""


@ auth : carl_DJ


@ time : 2021-3-6

"""



import hashlib


import threading


from time import *


from datetime import datetime,timedelta


import requests


import json




'''初始化全局变量'''



#自定义全局变量需要的线程数,10


thread_num = 10


#自定义全局变量每个线程需要循环的数量,10


one_worker_num = 10


#设定最开始的总时间


sum_time = 0.00


#设定最开始的成功连接数


success_count = 0

''' 后台登录常规操作'''

username = 'carldj'


password = hashlib.md5(b'123456').hexdigest()  #设置密码,且是md5加密方式


url = "http://www.xxx.com/energy/user/login/"


form_data = {"username":username,"password":password}


login_response = requests.post(url,data=form_data)


c = login_response.cookies



'''订单发送请求'''



def order():


    #引用全局变量


    global c


    global sum_time


    global success_count


    #获取执行发送订单请求前时间


    t1 = time()


    #设定url、form_data进行创建订单


    url1 = "http://www.xxx.com/energy/create_order/"


    from_data1 = {"restaurant_id":1136,


                  "menu_item_total":'12.00',


                  "menu_item_data": [{'id':2667868,'p':22,'q':3}]


                  }


    make_responst = requests.post(url1,data=from_data1,cookies = c)


    #获取请求结果


    res = make_responst.text


    #结果转换成字典赋值给变量id


    id = json.loads(res)['order_id']


    #断言判断是否提交成功


    assert  id != " "


    su_time =datetime.now()+ timedelta(hours=1)



    #设定url、form_data进行生成订单


    url2 = "http://www.xxx.com/energy/place_order/"


    from_data2 = {"restaurant_id": id,


                  "customer_name": 'carl_dj',


                  "mobile_number":username,


                  "delivery_address":"address message",


                  "pay_type":'cash',


                  "preorder":su_time


                  }


    place_responst = requests.post(url2, data=from_data2, cookies=c)


    res = place_responst.text


    #追加断言,判断结果是否有"success",有的话,说明订餐成功


    assert res == " success"


    print("订餐成功")


    #订单成功后,再次获取一下时间


    t2 = time()


    #获取订单的响应时间


    res_time = t2-t1


    #把响应时间写入txt文件


    result = open("E:\Private Folder\res.txt","a")  #路径直接写死,也可用os.path 来写路径


    result.write("成功订单响应时间:" + str(res_time)+ '\n')


    result.close()


    #也可以使用with打开文件,好处是不用关心文件是否关闭


    # with open ("E:\Private Folder\res.txt","a") as result1:


        # print(result1.read())



    #把每次成功订单数累加到全局变量sum_time中


    sum_time  = sum_time + res_time


    #把每次获取的成功订单数做累加,添加到全局变量success_count中


    success_count = success_count +1



'''嵌套指定循环次数的order()函数'''



def working()


    global one_worker_num


    for i in range(0,one_worker_num):


        order()



'''自定义main()函数,来执行多线程'''


def main():


    global thread_num


    #自定义一个空的数组,用来存放线程组


    threads = []


    #设置循环次数


    for i in range(thread_num):

        #将working()函数存放到线程中


        t = threading.Thread(target=working,name="T"+ str(i))


        #设定守护线程


        t.setDaemon(True)


        threads.append(t)


    #启动循环执行


    for t in threads:


        t.start()


    ##设置阻塞线程


    for t in threads:


        t.join()



if __name__ == "__main__":


    main()


    total_order = thread_num*one_worker_num


    avg_time = sum_time/success_count


    '''执行完之后,需要把数据写入到txt文件中'''


    #订单并发总数


    result.write("并发订单数:"+ str(total_order)+ "\n")


    #成功并发数


    result.write("成功并发数:"+ str(success_count) + "\n")


    #订单成功率


    result.write("订单成功率:"+ str(success_count/total_order*100)+ "%" + "\n")


    #成功订单响应时间


    result.write("成功订单总响应时间:"+ str(sum_time)+"\n")


    #成功订单平均响应时间


    result.write("成功平均响应时间:"+str(sum_time/success_count)+"\n")


    #TPS事务数/秒


    result.write("TPS:"+str(success_count/avg_time) + "\n")  #tps = 并发成功数/平均响应时间


    result.close()










分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-15 14:57 , Processed in 0.068811 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表