一、框架菜单

1.1 common模块

 1.2 其他

二、Excel接口测试案例编写

三、读取Excel测试封装(核心封装)

excel_utils.py  读取Excel中的数据

  1. import os
  2. import xlrd #内置模块、第三方模块pip install 自定义模块
  3.  
  4. class ExcelUtils():
  5. def __init__(self,file_path,sheet_name):
  6. self.file_path = file_path
  7. self.sheet_name = sheet_name
  8. self.sheet = self.get_sheet() # 整个表格对象
  9.  
  10. def get_sheet(self):
  11. wb = xlrd.open_workbook(self.file_path)
  12. sheet = wb.sheet_by_name(self.sheet_name)
  13. return sheet
  14.  
  15. def get_row_count(self):
  16. row_count = self.sheet.nrows
  17. return row_count
  18.  
  19. def get_col_count(self):
  20. col_count = self.sheet.ncols
  21. return col_count
  22.  
  23. def __get_cell_value(self,row_index, col_index):
  24. cell_value = self.sheet.cell_value(row_index,col_index)
  25. return cell_value
  26.  
  27. def get_merged_info(self):
  28. merged_info = self.sheet.merged_cells
  29. return merged_info
  30.  
  31. def get_merged_cell_value(self,row_index, col_index):
  32. """既能获取普通单元格的数据又能获取合并单元格数据"""
  33. cell_value = None
  34. for (rlow, rhigh, clow, chigh) in self.get_merged_info():
  35. if (row_index >= rlow and row_index < rhigh):
  36. if (col_index >= clow and col_index < chigh):
  37. cell_value = self.__get_cell_value(rlow, clow)
  38. break; # 防止循环去进行判断出现值覆盖的情况
  39. else:
  40. cell_value = self.__get_cell_value(row_index, col_index)
  41. else:
  42. cell_value = self.__get_cell_value(row_index, col_index)
  43. return cell_value
  44.  
  45. def get_sheet_data_by_dict(self):
  46. all_data_list = []
  47. first_row = self.sheet.row(0) #获取首行数据
  48. for row in range(1, self.get_row_count()):
  49. row_dict = {}
  50. for col in range(0, self.get_col_count()):
  51. row_dict[first_row[col].value] = self.get_merged_cell_value(row, col)
  52. all_data_list.append(row_dict)
  53. return all_data_list
  54.  
  55. if __name__=='__main__':
  56. current_path = os.path.dirname(__file__)
  57. excel_path = os.path.join( current_path,'..','samples/data/test_case.xlsx' )
  58. excelUtils = ExcelUtils(excel_path,"Sheet1")
  59. for row in excelUtils.get_sheet_data_by_dict():
  60. print( row )

testdata_utils.py 读取Excel中的数据后处理成需要的数据

  1. import os
  2. from common.excel_utils import ExcelUtils
  3. from common.config_utils import config
  4.  
  5. current_path = os.path.dirname(__file__)
  6. test_data_path = os.path.join( current_path,'..', config.CASE_DATA_PATH )
  7.  
  8. class TestdataUtils():
  9. def __init__(self,test_data_path = test_data_path):
  10. self.test_data_path = test_data_path
  11. self.test_data = ExcelUtils(test_data_path,"Sheet1").get_sheet_data_by_dict()
  12. self.test_data_by_mysql = SqlUtils().get_mysql_test_case_info()
  13.  
  14. def __get_testcase_data_dict(self):
  15. testcase_dict = {}
  16. for row_data in self.test_data:
  17. testcase_dict.setdefault( row_data['测试用例编号'],[] ).append( row_data )
  18. return testcase_dict
  19.  
  20. def def_testcase_data_list(self):
  21. testcase_list = []
  22. for k,v in self.__get_testcase_data_dict().items():
  23. one_case_dict = {}
  24. one_case_dict["case_id"] = k
  25. one_case_dict["case_info"] = v
  26. testcase_list.append( one_case_dict )
  27. return testcase_list
  28.  
  29. if __name__=="__main__":
  30. testdataUtils = TestdataUtils()
  31. for i in testdataUtils.def_testcase_data_list():
  32. print( i )

四、request封装(核心封装)

  1. requests_utils.py 包含post请求,get请求,异常,调用断言

  1. import ast
  2. import re
  3. import requests
  4. import jsonpath
  5. from requests.exceptions import RequestException
  6. from requests.exceptions import ProxyError
  7. from requests.exceptions import ConnectionError
  8. from common.config_utils import config
  9. from common.check_utils import CheckUtils
  10.  
  11. class RequestsUtils():
  12. def __init__(self):
  13. self.hosts = config.hosts
  14. self.headers = {"ContentType":"application/json;charset=utf-8"}
  15. self.session = requests.session()
  16. self.temp_variables = {}
  17.  
  18. def __get(self,get_info):
  19. try:
  20. url = self.hosts + get_info["请求地址"]
  21. response = self.session.get( url = url,
  22. params = ast.literal_eval(get_info["请求参数(get)"])
  23. )
  24. response.encoding = response.apparent_encoding
  25. if get_info["取值方式"] == "json取值":
  26. value = jsonpath.jsonpath( response.json(),get_info["取值代码"] )[0]
  27. self.temp_variables[ get_info["传值变量"] ] = value
  28. elif get_info["取值方式"] == "正则取值":
  29. value = re.findall(get_info["取值代码"],response.text)[0]
  30. self.temp_variables[get_info["传值变量"]] = value
  31. result = CheckUtils(response).run_check(get_info['期望结果类型'], get_info['期望结果'])
  32. except ProxyError as e:
  33. result = {'code': 4, 'result': '[%s]请求:代理错误异常' % (get_info["接口名称"])}
  34. except ConnectionError as e:
  35. result = {'code': 4, 'result': '[%s]请求:连接超时异常' % (get_info["接口名称"])}
  36. except RequestException as e:
  37. result = {'code': 4, 'result': '[%s]请求:Request异常,原因:%s' % (get_info["接口名称"], e.__str__())}
  38. except Exception as e:
  39. result = {'code':4,'result':'[%s]请求:系统异常,原因:%s'%(get_info["接口名称"],e.__str__())}
  40. return result
  41.  
  42. def __post(self,post_info):
  43. try:
  44. url = self.hosts + post_info["请求地址"]
  45. response = self.session.post( url = url,
  46. headers = self.headers,
  47. params = ast.literal_eval(post_info["请求参数(get)"]),
  48. # data = post_infos["提交数据(post)"],
  49. json=ast.literal_eval(post_info["提交数据(post)"])
  50. )
  51. response.encoding = response.apparent_encoding
  52. if post_info["取值方式"] == "json取值":
  53. value = jsonpath.jsonpath( response.json(),post_info["取值代码"] )[0]
  54. self.temp_variables[ post_info["传值变量"] ] = value
  55. elif post_info["取值方式"] == "正则取值":
  56. value = re.findall(post_info["取值代码"],response.text)[0]
  57. self.temp_variables[post_info["传值变量"]] = value
  58. #调用CheckUtils()
  59. result = CheckUtils(response).run_check(post_info['期望结果类型'],post_info['期望结果'])
  60. except ProxyError as e:
  61. result = {'code': 4, 'result': '[%s]请求:代理错误异常' % (post_info["接口名称"])}
  62. except ConnectionError as e:
  63. result = {'code': 4, 'result': '[%s]请求:连接超时异常' % (post_info["接口名称"])}
  64. except RequestException as e:
  65. result = {'code': 4, 'result': '[%s]请求:Request异常,原因:%s' % (post_info["接口名称"], e.__str__())}
  66. except Exception as e:
  67. result = {'code':4,'result':'[%s]请求:系统异常,原因:%s'%(post_info["接口名称"],e.__str__())}
  68. return result
  69.  
  70. def request(self,step_info):
  71. try:
  72. request_type = step_info["请求方式"]
  73. param_variable_list = re.findall('\\${\w+}', step_info["请求参数(get)"])
  74. if param_variable_list:
  75. for param_variable in param_variable_list:
  76. step_info["请求参数(get)"] = step_info["请求参数(get)"]\
  77. .replace(param_variable,'"%s"' % self.temp_variables.get(param_variable[2:-1]))
  78. if request_type == "get":
  79. result = self.__get( step_info )
  80. elif request_type == "post":
  81. data_variable_list = re.findall('\\${\w+}', step_info["提交数据(post)"])
  82. if data_variable_list:
  83. for param_variable in data_variable_list:
  84. step_info["提交数据(post)"] = step_info["提交数据(post)"] \
  85. .replace(param_variable, '"%s"' % self.temp_variables.get(param_variable[2:-1]))
  86. result = self.__post( step_info )
  87. else:
  88. result = {'code':1,'result':'请求方式不支持'}
  89. except Exception as e:
  90. result = {'code':4,'result':'用例编号[%s]的[%s]步骤出现系统异常,原因:%s'%(step_info['测试用例编号'],step_info["测试用例步骤"],e.__str__())}
  91. return result
  92.  
  93. def request_by_step(self,step_infos):
  94. self.temp_variables = {}
  95. for step_info in step_infos:
  96. temp_result = self.request( step_info )
  97. # print( temp_result )
  98. if temp_result['code']!=0:
  99. break
  100. return temp_result
  101.  
  102. if __name__=="__main__":
  103.  
  104. case_info = [
  105. {'请求方式': 'get', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"wxXXXXXxc16","secret":"XXXXXXXX"}', '提交数据(post)': '', '取值方式': 'json取值', '传值变量': 'token', '取值代码': '$.access_token', '期望结果类型': '正则匹配', '期望结果': '{"access_token":"(.+?)","expires_in":(.+?)}'},
  106. {'请求方式': 'post', '请求地址': '/cgi-bin/tags/create', '请求参数(get)': '{"access_token":${token}}', '提交数据(post)': '{"tag" : {"name" : "衡东"}}','取值方式': '无', '传值变量': '', '取值代码': '', '期望结果类型': '正则匹配', '期望结果': '{"tag":{"id":(.+?),"name":"衡东"}}'}
  107. ]
  108. RequestsUtils().request_by_step(case_info)

五、断言封装(核心封装)

  1. check_utils.py 断言封装,与实际结果核对

  1. import re
  2. import ast
  3.  
  4. class CheckUtils():
  5. def __init__(self,check_response=None):
  6. self.ck_response=check_response
  7. self.ck_rules = {
  8. '无': self.no_check,
  9. 'json键是否存在': self.check_key,
  10. 'json键值对': self.check_keyvalue,
  11. '正则匹配': self.check_regexp
  12. }
  13. self.pass_result = {
  14. 'code': 0,
  15. 'response_reason': self.ck_response.reason,
  16. 'response_code': self.ck_response.status_code,
  17. 'response_headers': self.ck_response.headers,
  18. 'response_body': self.ck_response.text,
  19. 'check_result': True,
  20. 'message': '' # 扩招作为日志输出等
  21. }
  22. self.fail_result = {
  23. 'code': 2,
  24. 'response_reason': self.ck_response.reason,
  25. 'response_code': self.ck_response.status_code,
  26. 'response_headers': self.ck_response.headers,
  27. 'response_body': self.ck_response.text,
  28. 'check_result': False,
  29. 'message': '' # 扩招作为日志输出等
  30. }
  31.  
  32. def no_check(self):
  33. return self.pass_result
  34.  
  35. def check_key(self,check_data=None):
  36. check_data_list = check_data.split(',') #把需要判断的值做切割,取出键值
  37. res_list = [] #存放每次比较的结果
  38. wrong_key = [] #存放比较失败key
  39. for check_data in check_data_list: #把切割的键值和取出响应结果中的所有的键一个一个对比
  40. if check_data in self.ck_response.json().keys():
  41. res_list.append(self.pass_result )
  42. else:
  43. res_list.append( self.fail_result )
  44. wrong_key.append(check_data) #把失败的键放进来,便于后续日志输出
  45. # print(res_list)
  46. # print(wrong_key)
  47. if self.fail_result in res_list:
  48. return self.fail_result
  49. else:
  50. return self.pass_result
  51.  
  52. def check_keyvalue(self,check_data=None):
  53. res_list = [] # 存放每次比较的结果
  54. wrong_items = [] # 存放比较失败 items
  55. for check_item in ast.literal_eval(check_data).items(): #literal_eval()安全性的把字符串转成字典,items()取出键值对
  56. if check_item in self.ck_response.json().items():
  57. res_list.append( self.pass_result )
  58. else:
  59. res_list.append( self.fail_result )
  60. wrong_items.append(check_item)
  61. # print( res_list )
  62. # print( wrong_items )
  63.  
  64. if self.fail_result in res_list:
  65. return self.fail_result
  66. else:
  67. return self.pass_result
  68.  
  69. def check_regexp(self,check_data=None):
  70. pattern = re.compile(check_data)
  71. if re.findall(pattern=pattern,string=self.ck_response.text): #匹配到了,不为空,为true
  72. return self.pass_result
  73. else:
  74. return self.fail_result
  75.  
  76. def run_check(self,check_type=None,check_data=None):
  77. code = self.ck_response.status_code
  78. if code == 200:
  79. if check_type in self.ck_rules.keys():
  80. result=self.ck_rules[check_type](check_data)
  81. return result
  82. else:
  83. self.fail_result['message'] = '不支持%s判断方法'%check_type
  84. return self.fail_result
  85. else:
  86. self.fail_result['message'] = '请求的响应状态码非%s'%str(code)
  87. return self.fail_result
  88.  
  89. if __name__=="__main__":
  90. # 检查键是否存在,{"access_token":"hello","expires_":7200} 设为响应结果,"access_token,expires_in" 为检查对象值
  91. CheckUtils({"access_token":"hello","expires_":7200}).check_key("access_token,expires_in")
  92. #检查键值对是否存在
  93. CheckUtils({"access_token":"hello","expires_i":7200}).check_keyvalue('{"expires_in": 7200}')
  94. #正则对比
  95. #TURE
  96. print(CheckUtils('{"access_token":"hello","expires_in":7200}').check_regexp('"expires_in":(.+?)'))
  97. #False
  98. print(CheckUtils('{"access_token":"hello","expires":7200}').check_regexp('"expires_in":(.+?)'))

六、api_testcase下的api_test.py 封装

  1. import warnings
  2. import unittest
  3. import paramunittest
  4. from common.testdata_utils import TestdataUtils
  5. from common.requests_utils import RequestsUtils
  6.  
  7. #如果是mysql数据源的话切换成 def_testcase_data_list_by_mysql() exccel数据源:def_testcase_data_list()
  8.  
  9. case_infos = TestdataUtils().def_testcase_data_list_by_mysql()
  10.  
  11. @paramunittest.parametrized(
  12. *case_infos
  13. )
  14.  
  15. class APITest(paramunittest.ParametrizedTestCase):
  16. def setUp(self) -> None:
  17. warnings.simplefilter('ignore', ResourceWarning) #不会弹出警告提示
  18.  
  19. def setParameters(self, case_id, case_info):
  20. self.case_id = case_id
  21. self.case_info = case_info
  22.  
  23. def test_api_common_function(self):
  24. '''测试描述'''
  25. self._testMethodName = self.case_info[0].get("测试用例编号")
  26. self._testMethodDoc = self.case_info[0].get("测试用例名称")
  27. actual_result = RequestsUtils().request_by_step(self.case_info)
  28. self.assertTrue( actual_result.get('check_result'),actual_result.get('message') )
  29.  
  30. if __name__ == '__main__':
  31. unittest.main()

七、common下的log_utils.py 封装

  1. import os
  2. import logging
  3. import time
  4. from common.config_utils import config
  5.  
  6. current_path = os.path.dirname(__file__)
  7. log_output_path = os.path.join( current_path,'..', config.LOG_PATH )
  8.  
  9. class LogUtils():
  10. def __init__(self,log_path=log_output_path):
  11. self.log_name = os.path.join( log_output_path ,'ApiTest_%s.log'%time.strftime('%Y_%m_%d') )
  12. self.logger = logging.getLogger("ApiTestLog")
  13. self.logger.setLevel( config.LOG_LEVEL )
  14.  
  15. console_handler = logging.StreamHandler() # 控制台输出
  16. file_handler = logging.FileHandler(self.log_name,'a',encoding='utf-8') # 文件输出
  17. formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
  18. console_handler.setFormatter(formatter)
  19. file_handler.setFormatter(formatter)
  20.  
  21. self.logger.addHandler( console_handler )
  22. self.logger.addHandler( file_handler )
  23.  
  24. console_handler.close() # 防止打印日志重复
  25. file_handler.close() # 防止打印日志重复
  26.  
  27. def get_logger(self):
  28. return self.logger
  29.  
  30. logger = LogUtils().get_logger() # 防止打印日志重复
  31.  
  32. if __name__ == '__main__':
  33. logger.info('hello')

八、common下的config_utils.py的封装

配置文件的编写:

对配置文件的读取封装:

  1. import os
  2. import configparser
  3.  
  4. current_path = os.path.dirname(__file__)
  5. cfgpath = os.path.join(current_path, "../conf/local_config.ini")
  6. print(cfgpath)
  7.  
  8. class ConfigUtils:
  9. def __init__(self,config_path=cfgpath):
  10. self.__conf=configparser.ConfigParser()
  11. self.__conf.read(config_path, encoding="utf-8")
  12.  
  13. def read_ini(self,sec,option):
  14. value=self.__conf.get(sec,option)
  15. return value
  16.  
  17. @property
  18. def hosts(self):
  19. value=self.read_ini('default','hosts')
  20. return value
  21.  
  22. @property
  23. def LOG_PATH(self):
  24. value = self.read_ini('path', 'LOG_PATH')
  25. return value
  26.  
  27. @property
  28. def CASE_DATA_PATH(self):
  29. value = self.read_ini('path', 'CASE_DATA_PATH')
  30. return value
  31.  
  32. @property
  33. def REPORT_PATH(self):
  34. value = self.read_ini('path', 'REPORT_PATH')
  35. return value
  36.  
  37. @property
  38. def LOG_LEVEL(self):
  39. value = int(self.read_ini('log', 'LOG_LEVEL'))
  40. return value
  41.  
  42. @property
  43. def smtp_server(self):
  44. smtp_server_value = self.read_ini('email', 'smtp_server')
  45. return smtp_server_value
  46.  
  47. @property
  48. def smtp_sender(self):
  49. smtp_sender_value = self.read_ini('email', 'smtp_sender')
  50. return smtp_sender_value
  51.  
  52. @property
  53. def smtp_password(self):
  54. smtp_password_value = self.read_ini('email', 'smtp_password')
  55. return smtp_password_value
  56.  
  57. @property
  58. def smtp_receiver(self):
  59. smtp_receiver_value = self.read_ini('email', 'smtp_receiver')
  60. return smtp_receiver_value
  61.  
  62. @property
  63. def smtp_cc(self):
  64. smtp_cc_value = self.read_ini('email', 'smtp_cc')
  65. return smtp_cc_value
  66.  
  67. @property
  68. def smtp_subject(self):
  69. smtp_subject_value = self.read_ini('email', 'smtp_subject')
  70. return smtp_subject_value
  71.  
  72. config=ConfigUtils()
  73.  
  74. if __name__=='__main__':
  75. current_path = os.path.dirname(__file__)
  76. cfgpath = os.path.join(current_path, "../conf/local_config.ini")
  77. config_u=ConfigUtils()
  78. print(config_u.hosts)
  79. print(config_u.LOG_LEVEL)

九、test_runner下的run_case.py 封装

  1. class RunCase():
  2. def __init__(self):
  3. self.test_case_path = test_case_path
  4. self.report_path = test_report_path
  5. self.title = 'P1P2接口自动化测试报告'
  6. self.description = '自动化接口测试框架'
  7. self.tester = '测试开发组'
  8. def load_test_suite(self):
  9. discover = unittest.defaultTestLoader.discover(start_dir=self.test_case_path,
  10. pattern='api_test.py',
  11. top_level_dir=self.test_case_path)
  12. all_suite = unittest.TestSuite()
  13. all_suite.addTest( discover )
  14. return all_suite
  15. def run(self):
  16. report_dir = HTMLTestReportCN.ReportDirectory(self.report_path)
  17. report_dir.create_dir(self.title)
  18. report_file_path = HTMLTestReportCN.GlobalMsg.get_value('report_path')
  19. fp = open( report_file_path ,'wb' )
  20. runner = HTMLTestReportCN.HTMLTestRunner(stream=fp,
  21. title=self.title,
  22. description=self.description,
  23. tester=self.tester)
  24. runner.run( self.load_test_suite() )
  25. fp.close()
  26. return report_file_path
  27.  
  28. if __name__=='__main__':
  29. report_path = RunCase().run()
  30. EmailUtils(open(report_path, 'rb').read(), report_path).send_mail()

十、common下的email_utils.py 封装

  1. import os
  2. import smtplib
  3. from email.mime.text import MIMEText
  4. from email.mime.multipart import MIMEMultipart
  5. from common.config_utils import config
  6.  
  7. class EmailUtils():
  8. def __init__(self,smtp_body,smtp_attch_path=None):
  9. self.smtp_server = config.smtp_server
  10. self.smtp_sender = config.smtp_sender
  11. self.smtp_password = config.smtp_password
  12. self.smtp_receiver = config.smtp_receiver
  13. self.smtp_cc = config.smtp_cc
  14. self.smtp_subject = config.smtp_subject
  15. self.smtp_body = smtp_body
  16. self.smtp_attch = smtp_attch_path
  17.  
  18. def mail_message_body(self):
  19. message = MIMEMultipart()
  20. message['from'] = self.smtp_sender
  21. message['to'] = self.smtp_receiver
  22. message['Cc'] = self.smtp_cc
  23. message['subject'] = self.smtp_subject
  24. message.attach( MIMEText(self.smtp_body,'html','utf-8') )
  25. if self.smtp_attch:
  26. attach_file = MIMEText(open(self.smtp_attch, 'rb').read(), 'base64', 'utf-8')
  27. attach_file['Content-Type'] = 'application/octet-stream'
  28. attach_file.add_header('Content-Disposition', 'attachment', filename=('gbk', '', os.path.basename(self.smtp_attch)))
  29. message.attach(attach_file)
  30. return message
  31.  
  32. def send_mail(self):
  33. smtp = smtplib.SMTP()
  34. smtp.connect(self.smtp_server)
  35. smtp.login(user=self.smtp_sender, password=self.smtp_password)
  36. smtp.sendmail(self.smtp_sender,self.smtp_receiver.split(",")+ self.smtp_cc.split(","), self.mail_message_body().as_string())
  37.  
  38. if __name__=='__main__':
  39. html_path = os.path.dirname(__file__) + '/../test_reports/接口自动化测试报告V1.1/接口自动化测试报告V1.1.html'
  40. EmailUtils('<h3 align="center">自动化测试报告</h3>',html_path).send_mail()

python_reques接口测试框架,Excel作为案例数据源的更多相关文章

  1. Web自动化框架之五一套完整demo的点点滴滴(excel功能案例参数化+业务功能分层设计+mysql数据存储封装+截图+日志+测试报告+对接缺陷管理系统+自动编译部署环境+自动验证false、error案例)

    标题很大,想说的很多,不知道从那开始~~直接步入正题吧 个人也是由于公司的人员的现状和项目的特殊情况,今年年中后开始折腾web自动化这块:整这个原因很简单,就是想能让自己偷点懒.也让减轻一点同事的苦力 ...

  2. python接口测试框架遇到的坑(一)excel数字转文本

    一.遇到的问题 python编写接口测试框架中,接口用例使用excel维护,其中预期值(code码的值)20000和实际值总是不一致,后来通过打印type发现一个是unicode,一个是float. ...

  3. 【转】基于Python的接口测试框架实例

    下面小编就为大家带来一篇基于Python的接口测试框架实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧   背景 最近公司在做消息推送,那么自然就会产生很多接口,测试 ...

  4. 基于Python的接口测试框架实例

    文章来源:http://www.jb51.net/article/96481.htm 下面小编就为大家带来一篇基于Python的接口测试框架实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. ...

  5. Python+API接口测试框架设计(pytest)

    1.测试框架简介 整个接口测试框架的设计图如下: base:存放的是请求方法二次封装 common:存放的是自定义工具,操作excel,yaml文件等 data:存放的是公共动态数据,如data.xl ...

  6. python+API接口测试框架设计(unittest)

    1.测试框架简介 整个接口测试框架的设计图如下: basepage:存放的是公共的方法 common:存放的是自定义工具 data:存放的是公共动态数据,如BB.xls/ Id.md log:存放的是 ...

  7. 初探接口测试框架--python系列7

    点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...

  8. 初探接口测试框架--python系列6

    点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...

  9. Python接口测试实战4(上) - 接口测试框架实战

    如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...

随机推荐

  1. LA3177长城守卫

    题意:      有n个人围成一个圈,每个人都有r[i]个礼物,任意两个相邻的人的礼物不能有重复的,问满足所有相邻不重复的最少礼物种数是多少?就是问最少多少种礼物能让任意相邻的两个人的礼物不重复. 思 ...

  2. hdu3117 斐波那契前后4位

    题意:       求斐波那契的前后4位,n <= 10^8. 思路:       至于前四位,和hdu1568的求法一样:       http://blog.csdn.net/u013761 ...

  3. poj2418map或者字典树

    题意:      给你一些串,然后求出每个串出现的概率. 思路:      简单题目,做法也很多,我用字典树做了下,然后又用map做了下,其实这个题目我感觉直接排序一遍之后线性输出应该是最简单最快的( ...

  4. MS08_067漏洞攻击

    MS08_067 MS08_067是典型的缓冲区溢出漏洞,Windows的Server服务在处理特制RPC请求时存在缓冲区溢出漏洞,远程攻击者可以通过发送恶意的RPC请求触发这个溢出,导致完全入侵用户 ...

  5. CVE-2013-0077:Microsoft DirectShow quartz.dll m2p 文件堆溢出漏洞简单分析

    0x01 前言 2012 年 10 月 5 日,exploit-db 漏洞公布站点上发布了 QQplayer.exe 3.7.892 m2p quartz.dll Heap Pointer OverW ...

  6. React 代码共享最佳实践方式

    任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题.在React中实现逻辑复用通常有以下几种方式:Mixin.高阶组件(HOC).修饰器(decorator).Render Props.Ho ...

  7. 2020.12.20vj补题

    A - Insomnia cure 题意:一共s只龙,每隔k,l,m,n只龙就会受伤,问这s只龙有多少龙是受伤的 思路:看起来题目范围并不是很多,直接进行循环判断 代码: 1 #include< ...

  8. 迷失在Mysql的锁世界~

    1.饮料 这是一杯饮料. 这是3杯饮料,每杯饮料的味道各不相同. 但是人类并不称呼[饮料]为[饮料],而是称呼[饮料]为[记录]. 2.红章鱼 这个红色的,长的像章鱼的家伙,我们就叫它红章鱼~ 红章鱼 ...

  9. OO随笔之魔鬼的第一单元——多项式求导

    OO是个借助Java交我们面向对象的课,可是萌新们总是喜欢带着面向过程的脑子去写求导,然后就是各种一面(main)到底.各种方法杂糅,然后就是被hack的很惨. 第一次作业:萌新入门面向对象 题目分析 ...

  10. Java Arrays.sort()重写comparator方法

    先看一下接口 Arrays.sort(T[],Comparator<? super T> c); comparator要重写compare方法 compare方法大概长这样,返回值> ...