Python concurrent requests (dry goods)

In the server-side test, in addition to considering the compatibility of the service-side business functions and APIs, the stability of the server-side and the carrying capacity of the server-side under high concurrent requests need to be considered. Regarding the number of concurrency and specific response time requirements, in fact, the form of each product is different, and it is difficult to use standard terms to unify. It depends on the business form that the tested component is facing. If the business form is a product that is rarely used, there is actually no requirement for performance. Therefore, this must be based on the architecture design of the component under test, the amount of load and business goals. This article mainly shares the use of Python to write a simple test code for concurrent requests.

In the concurrent programming model of Python, the main points involved are threads and processes, as well as corresponding coroutines. And locust is mainly designed based on coroutines, which can be understood as microthreads. In IO-intensive and CPU-intensive, if it is IO-intensive, it is recommended to use multithreading to be more efficient, if it is CPU-intensive, it is recommended to use multi-process method to be more efficient. This article mainly shares the method based on IO intensiveness, that is, multi-threading. The way to start a thread is very simple. We can use functional programming or object-oriented programming. See the following specific case code, functional way:

from threading import  Thread
import  time as t
import  random


def job(name):
   print('我是{0},我要开始工作啦'.format(name))

if __name__ == '__main__':
   t=Thread(target=job,args=('李四',))
   t.start()
   print('主线程执行结束')

Object-oriented approach:

from threading import  Thread
import  time as t
import  random

class Job(Thread):
   def __init__(self,name):
      super().__init__()
      self.name=name

   def run(self) -> None:
      print('我是{0},我要开始工作啦'.format(self.name))

if __name__ == '__main__':
   t=Job('李四')
   t.start()
   print('主线程程序执行结束')
其实在Thread的类中,并没有返回被测函数的返回值,也就是说我们在测试API接口的时候,需要拿到被测接口的状态码,请求响应时间,和响应数据,那么我们就需要重新Thread类继承后对run()的方法进行重写,拿到被测函数中我们所期望的数据,具体案例代码如下:
#!coding:utf-8 
from threading import  Thread


class ThreadTest(Thread):
   def __init__(self,func,args=()):
      '''
      :param func: 被测试的函数
      :param args: 被测试的函数的返回值
      '''
      super(ThreadTest,self).__init__()
      self.func=func
      self.args=args

   def run(self) -> None:
      self.result=self.func(*self.args)

   def getResult(self):
      try:
         return self.result
      except BaseException as e:
         return e.args[0]

Here we take the test of Baidu homepage as a case. After concurrent requests are received, the response time and status code of the concurrent request are obtained, and then the median and other data are obtained according to the response time. The specific complete case code is as follows:

#!/usr/bin/env python
#!coding:utf-8
from threading import  Thread
import  requests
import  matplotlib.pyplot as plt
import  datetime
import  time
import  numpy as np
import  json


class ThreadTest(Thread):
   def __init__(self,func,args=()):
      '''
      :param func: 被测试的函数
      :param args: 被测试的函数的返回值
      '''
      super(ThreadTest,self).__init__()
      self.func=func
      self.args=args

   def run(self) -> None:
      self.result=self.func(*self.args)

   def getResult(self):
      try:
         return self.result
      except BaseException as e:
         return e.args[0]


def baiDu(code,seconds):
   '''
   :param code: 状态码
   :param seconds: 请求响应时间
   :return:
   '''
   r=requests.get(url='http://www.baidu.com/')
   code=r.status_code
   seconds=r.elapsed.total_seconds()
   return code,seconds

def calculationTime(startTime,endTime):
   '''计算两个时间之差,单位是秒'''
   return (endTime-startTime).seconds


def getResult(seconds):
   '''获取服务端的响应时间信息'''
   data={
    
    
      'Max':sorted(seconds)[-1],
      'Min':sorted(seconds)[0],
      'Median':np.median(seconds),
      '99%Line':np.percentile(seconds,99),
      '95%Line':np.percentile(seconds,95),
      '90%Line':np.percentile(seconds,90)
   }
   return data


def highConcurrent(count):
   '''
   对服务端发送高并发的请求
   :param cout: 并发数
   :return:
   '''
   startTime=datetime.datetime.now()
   sum=0
   list_count=list()
   tasks=list()
   results = list()
   #失败的信息
   fails=[]
   #成功任务数
   success=[]
   codes = list()
   seconds = list()

   for i in range(1,count):
      t=ThreadTest(baiDu,args=(i,i))
      tasks.append(t)
      t.start()

   for t in tasks:
      t.join()
      if t.getResult()[0]!=200:
         fails.append(t.getResult())
      results.append(t.getResult())

   endTime=datetime.datetime.now()
   for item in results:
      codes.append(item[0])
      seconds.append(item[1])
   for i in range(len(codes)):
      list_count.append(i)

   #生成可视化的趋势图
   fig,ax=plt.subplots()
   ax.plot(list_count,seconds)
   ax.set(xlabel='number of times', ylabel='Request time-consuming',
          title='olap continuous request response time (seconds)')
   ax.grid()
   fig.savefig('olap.png')
   plt.show()

   for i in seconds:
      sum+=i
   rate=sum/len(list_count)
   # print('\n总共持续时间:\n',endTime-startTime)
   totalTime=calculationTime(startTime=startTime,endTime=endTime)
   if totalTime<1:
      totalTime=1
   #吞吐量的计算
   try:
      throughput=int(len(list_count)/totalTime)
   except Exception as e:
      print(e.args[0])
   getResult(seconds=seconds)
   errorRate=0
   if len(fails)==0:
      errorRate=0.00
   else:
      errorRate=len(fails)/len(tasks)*100
   throughput=str(throughput)+'/S'
   timeData=getResult(seconds=seconds)
   dict1={
    
    
      '吞吐量':throughput,
      '平均响应时间':rate,
      '响应时间':timeData,
      '错误率':errorRate,
      '请求总数':len(list_count),
      '失败数':len(fails)
   }
   return  json.dumps(dict1,indent=True,ensure_ascii=False)

if __name__ == '__main__':
    print(highConcurrent(count=1000))

After the above code is executed, a visual request response time and other information will be formed, and the following information will be displayed after execution:

{
    
    
   "吞吐量": "500/S",
   "平均响应时间": 0.08835436199999998,
   "响应时间": {
    
    
      "Max": 1.5547,
      "Min": 0.068293,
      "Median": 0.0806955,
      "99%Line": 0.12070111,
      "95%Line": 0.10141509999999998,
      "90%Line": 0.0940216
   },
   "错误率": 0.0,
   "请求总数": 1000,
   "失败数": 0
}

Thank you for your reading and attention. We will update it again in the future and provide it as an interface that can be specifically called. Using code, you can quickly verify the carrying capacity of the server and whether there is TimeOut in the work.

In the technology industry, you must improve your technical skills and enrich your practical experience in automation projects. This will be very helpful for your career planning in the next few years and the depth of your testing technology.

In the interview season of the Golden 9th and the Silver 10th, the job-hopping season, organizing interview questions has become my habit for many years! The following is my collection and sorting in recent years, the whole is organized around [software testing], the main content includes: python automation test exclusive video, Python automation details, a full set of interview questions and other knowledge content.

For software testing friends, it should be the most comprehensive and complete interview preparation warehouse. In order to better organize each module, I also refer to many high-quality blog posts and projects on the Internet, and strive not to miss every knowledge point. Friends relied on these contents to review and got offers from big factories such as BATJ. This warehouse has also helped many learners of software testing, and I hope it can help you too!

May you and I meet and you will find something! Welcome to follow the WeChat public account: [Sad Spicy Article] Receive a 216-page software test engineer interview book for free. And the corresponding video learning tutorials are free to share!

Guess you like

Origin blog.csdn.net/weixin_50829653/article/details/112863403