当前位置:   article > 正文

Python 接口测试框架_python接口框架

python接口框架

目录结构定义

首先来看一下项目整体的结构

框架结构

 

代码结构

 

Excel 文件结构

 

代码详细解析

1.工具包 tools

封装操作 excel 方法 excel_operation.py

  1. import xlrd
  2. from config.config import PROJECT_PATH
  3. class OperationExcel:
  4. def __init__(self, file_name=None, sheet_id=0):
  5. if file_name:
  6. self.file_name = PROJECT_PATH + '/data/' + file_name
  7. self.sheet_id = sheet_id
  8. else:
  9. try:
  10. self.file_name = PROJECT_PATH + '/data/case.xlsx'
  11. self.sheet_id = 0
  12. except FileExistsError:
  13. raise FileExistsError("the default testcase file not found")
  14. self.book = self.get_book()
  15. self.data = self.get_data()
  16. # 获取工作簿
  17. def get_book(self):
  18. book = xlrd.open_workbook(self.file_name)
  19. return book
  20. # 获取 sheets 的内容
  21. def get_data(self):
  22. book = self.book
  23. tables = book.sheets()[self.sheet_id]
  24. return tables
  25. # 获取所有 sheet 的名字
  26. def get_sheet_name(self):
  27. book = self.book
  28. return book.sheet_names()
  29. # 获取所有 sheets
  30. def get_sheets(self):
  31. book = self.book
  32. sheets = book.sheets()
  33. return sheets
  34. # 获取某个单元格的内容
  35. def get_cell_value(self, row, col):
  36. return self.data.cell_value(row, col)
  37. # 获取单元格的行数
  38. def get_lines(self):
  39. tables = self.data
  40. case_rows = tables.nrows - 1
  41. return case_rows
  42. # 获取某一列的内容
  43. def get_cols_data(self, col_id=None):
  44. if col_id is not None:
  45. cols = self.data.col_values(col_id)
  46. else:
  47. cols = self.data.col_values(0)
  48. return cols
  49. # 获取某一行的内容
  50. def get_rows_data(self, row_id=None):
  51. if row_id is not None:
  52. rows = self.data.row_values(row_id)
  53. else:
  54. rows = self.data.row_values(0)
  55. return rows
  56. # 获取某个 caseid 对应的行号
  57. def get_row_num(self, case_id):
  58. num = 0
  59. cols_data = self.get_cols_data()
  60. for col_data in cols_data:
  61. if case_id in col_data:
  62. return num
  63. num += 1

使用 xlrd 库来操作 excel,同时,该类只做最底层的 excel 数据提取,不做任何业务相关的判断。后面会陆续增加 json,yaml 等数据结构的操作工具。

中间数据操作层 operate_data.py

  1. from config.config import ExcelConfData
  2. class OperateExcelData(object):
  3. def get_caseid(self):
  4. return ExcelConfData.caseid
  5. def get_url(self):
  6. return ExcelConfData.url
  7. def get_method(self):
  8. return ExcelConfData.method
  9. def get_is_auto_run(self):
  10. return ExcelConfData.automated
  11. def get_header(self):
  12. return ExcelConfData.header
  13. def get_data(self):
  14. return ExcelConfData.data
  15. def get_casename(self):
  16. return ExcelConfData.casename
  17. def get_statuscode(self):
  18. return ExcelConfData.statuscode
  19. def get_checkpoints(self):
  20. return ExcelConfData.checkpoints
  21. def get_validate(self):
  22. return ExcelConfData.validate
  23. def get_caseuniqueid(self):
  24. return ExcelConfData.caseuniqueid
  25. def get_authtype(self):
  26. return ExcelConfData.authtype

属于操作数据的中间层,从配置文件中拿到我们定义好的 excel 结构,这样,如果我们的 excel 结构有变化,只需要修改配置文件即可

配置文件中的 excel 结构如下

  1. class ExcelConfData:
  2. caseid = '0'
  3. casename = '1'
  4. caselevel = '2'
  5. preconditions = '3'
  6. testcontent = '4'
  7. expect = '5'
  8. casecategory = '6'
  9. automated = '7' # 1 是自动运行, 2 是非自动运行
  10. caseuniqueid = '1' # 8
  11. method = '9'
  12. url = '10'
  13. data = '11'
  14. header = '12'
  15. statuscode = '13'
  16. checkpoints = '14'
  17. validate = '15'
  18. parameterize = '16'
  19. result = '17'
  20. authtype = '18' # 0:admin, 1:common user, 2:not login

获取测试文件中数据工具 get_data.py

  1. from tools.excel_operation import OperationExcel
  2. from tools.operate_data import OperateExcelData
  3. class GetExcelData(object):
  4. def __init__(self, filename=None, sheet_id=0):
  5. self.operate_excel = OperationExcel(filename, sheet_id)
  6. self.operate_data = OperateExcelData()
  7. # 获取 sheet 个数
  8. def get_sheets(self):
  9. sheet_num = self.operate_excel.get_sheets()
  10. return len(sheet_num)
  11. # 获取 excel 行数,即用例个数
  12. def get_case_lines(self):
  13. return self.operate_excel.get_lines()
  14. # 获取是否执行
  15. def get_is_auto_run(self, row):
  16. auto_flag = False
  17. col = int(self.operate_data.get_is_auto_run())
  18. run_model = self.operate_excel.get_cell_value(row, col)
  19. if run_model == 1:
  20. auto_flag = True
  21. else:
  22. auto_flag = False
  23. return auto_flag
  24. # 获取请求方式
  25. def get_request_method(self, row):
  26. col = int(self.operate_data.get_method())
  27. request_method = self.operate_excel.get_cell_value(row, col)
  28. return request_method
  29. # 获取 url
  30. def get_request_url(self, row):
  31. col = int(self.operate_data.get_url())
  32. url = self.operate_excel.get_cell_value(row, col)
  33. return url
  34. # 获取请求数据
  35. def get_request_data(self, row):
  36. col = int(self.operate_data.get_data())
  37. data = self.operate_excel.get_cell_value(row, col)
  38. return data
  39. # 获取 status code
  40. def get_response_statuscode(self, row):
  41. col = int(self.operate_data.get_statuscode())
  42. statuscode = self.operate_excel.get_cell_value(row, col)
  43. return statuscode
  44. # 获取 checkpoints
  45. def get_checkpoints(self, row):
  46. col = int(self.operate_data.get_checkpoints())
  47. checkpoints = self.operate_excel.get_cell_value(row, col)
  48. return checkpoints
  49. # 获取 validate
  50. def get_validate(self, row):
  51. col = int(self.operate_data.get_validate())
  52. validate = self.operate_excel.get_cell_value(row, col)
  53. return validate
  54. # 获取测试用例唯一 ID
  55. def get_caseuniqueid(self, row):
  56. col = int(self.operate_data.get_caseuniqueid())
  57. caseuniqueid = self.operate_excel.get_cell_value(row, col)
  58. if isinstance(caseuniqueid, float):
  59. caseuniqueid = int(caseuniqueid)
  60. return str(caseuniqueid)
  61. # 获取 header 信息
  62. def get_header(self, row):
  63. col = int(self.operate_data.get_header())
  64. header = self.operate_excel.get_cell_value(row, col)
  65. return header
  66. # 获取是否需要鉴权信息
  67. def get_authtype(self, row):
  68. col = int(self.operate_data.get_authtype())
  69. authtype = self.operate_excel.get_cell_value(row, col)
  70. return authtype

获取到测试数据中业务相关的数据,例如是否自动化执行,是否使用 header,是否需要鉴权信息等。

通用工具文件 common_util.py

  1. import json
  2. import operator
  3. from config.config import UserInfo, EnvConf
  4. import requests
  5. class CommonUtil(object):
  6. def is_contain(self, str1, str2):
  7. """
  8. :param str1: 原始字符串
  9. :param str2: 被查找的字符串
  10. :return: True or False
  11. """
  12. flag = None
  13. if str1 in str2:
  14. flag = True
  15. else:
  16. flag = False
  17. return flag
  18. def is_equal_dict(self, d1, d2):
  19. if isinstance(d1, str):
  20. d1 = json.loads(d1)
  21. if isinstance(d2, str):
  22. d2 = json.loads(d2)
  23. return operator.eq(d1, d2)
  24. def adminlogin():
  25. url = f"http://{EnvConf.host}:{EnvConf.port}/api/user-management/tokens"
  26. data = UserInfo.admininfo
  27. resp = requests.post(url=url, json=data)
  28. try:
  29. token = f"Bearer {resp.json()['data']['access_token']}"
  30. except:
  31. raise
  32. return token
  33. def commonlogin():
  34. url = f"http://{EnvConf.host}:{EnvConf.port}/api/user-management/tokens"
  35. data = UserInfo.commoninfo
  36. resp = requests.post(url=url, json=data)
  37. try:
  38. token = f"Bearer {resp.json()['data']['access_token']}"
  39. except:
  40. raise
  41. return token

主要编写一些验证器,或者通用的获取登陆 token 信息等函数。这里的验证器还很简单,后面再慢慢添加,比如正则校验,解析 json 校验等。

2. 基础包 base

封装 http 请求 runmethod.py

  1. import requests
  2. import json
  3. class RunMethod(object):
  4. def __init__(self):
  5. self.verify = False
  6. self.headers = None
  7. def post_main(self, url, data=None, header=None):
  8. res = None
  9. if header is not None:
  10. res = requests.post(url=url, data=data, headers=header)
  11. else:
  12. res = requests.post(url=url, data=data)
  13. return res.json()
  14. def get_main(self, url, data=None, header=None, param=None):
  15. res = None
  16. if header is not None:
  17. res = requests.get(url=url, data=data, headers=header, verify=self.verify, params=param)
  18. else:
  19. res = requests.get(url=url, data=data, verify=self.verify, params=param)
  20. return res.json()
  21. def del_main(self, url, data=None, header=None):
  22. res = None
  23. if header is not None:
  24. res = requests.delete(url=url, data=data, headers=header)
  25. else:
  26. res = requests.delete(url=url, data=data)
  27. return res.json()
  28. def run_main(self, method, url, data=None, header=None):
  29. res = None
  30. if method == 'POST':
  31. res = self.post_main(url, data, header)
  32. elif method == 'GET':
  33. res = self.get_main(url, data, header)
  34. else:
  35. res = self.del_main(url, data, header)
  36. return json.dumps(res, ensure_ascii=False, sort_keys=True, indent=2)

当前的封装还是很简陋的,并没有过多的异常处理,参数校验等,后面会对这方面做一下增强。

runmock.py 是用来做 mock 数据的,以后再用。

提取 excel 数据文件 basetest.py

  1. from tools.get_data import GetExcelData
  2. from base.runmethod import RunMethod
  3. from tools.common_util import CommonUtil
  4. from config.config import EnvConf, Header
  5. import json
  6. from tools.excel_operation import OperationExcel
  7. from tools.common_util import adminlogin, commonlogin
  8. class CaseDataAllSheets:
  9. def __init__(self, filename=None):
  10. self.filename = filename
  11. self.opera_excel = OperationExcel(filename)
  12. self.sheet_nums = self.opera_excel.get_sheets()
  13. def get_all_sheets_data(self):
  14. total_data = {
  15. "sheet-data": [],
  16. 'case_data_ids': []
  17. }
  18. for i in range(len(self.sheet_nums)):
  19. data = {}
  20. sheet_name = self.opera_excel.get_sheet_name()[i]
  21. casedata = CaseData(filename=self.filename, sheet_id=i)
  22. test_data, case_data_ids = casedata.get_testcase_data()
  23. data[sheet_name] = test_data
  24. total_data['sheet-data'].append(data)
  25. total_data['case_data_ids'].append(case_data_ids)
  26. return total_data
  27. class CaseData:
  28. def __init__(self, filename=None, sheet_id=0):
  29. self.exceldata = GetExcelData(filename, sheet_id)
  30. self.casenums = self.exceldata.get_case_lines()
  31. def get_testcase_data(self):
  32. test_data = {
  33. 'parameterize': []
  34. }
  35. case_data_ids = []
  36. for case in range(1, self.casenums + 1):
  37. if self.exceldata.get_is_auto_run(case):
  38. case_data_json = {
  39. 'request-data': {},
  40. 'response-data': {}
  41. }
  42. case_method = self.exceldata.get_request_method(case)
  43. data_url = self.exceldata.get_request_url(case)
  44. case_url = f"http://{EnvConf.host}:{EnvConf.port}" + data_url
  45. case_data = self.exceldata.get_request_data(case)
  46. if case_data != '':
  47. try:
  48. case_data = json.loads(case_data)
  49. except:
  50. raise
  51. case_header = self.exceldata.get_header(case)
  52. if case_header == '':
  53. case_header = Header.headers
  54. else:
  55. try:
  56. case_header = json.loads(case_header)
  57. except:
  58. raise
  59. case_statuscode = self.exceldata.get_response_statuscode(case)
  60. case_checkpoint = self.exceldata.get_checkpoints(case)
  61. case_validate = self.exceldata.get_validate(case)
  62. case_uniqueid = self.exceldata.get_caseuniqueid(case)
  63. print(case_uniqueid)
  64. print(type(case_uniqueid))
  65. case_authtype = self.exceldata.get_authtype(case)
  66. if case_authtype == 0:
  67. token = adminlogin()
  68. case_header['authorization'] = token
  69. elif case_authtype == 1:
  70. token = commonlogin()
  71. case_header['authorization'] = token
  72. else:
  73. pass
  74. case_data_json['request-data']['url'] = case_url
  75. case_data_json['request-data']['data'] = case_data
  76. case_data_json['request-data']['header'] = case_header
  77. case_data_json['request-data']['method'] = case_method
  78. case_data_json['response-data']['statuscode'] = case_statuscode
  79. case_data_json['response-data']['checkpoint'] = case_checkpoint
  80. case_data_json['response-data']['validate'] = case_validate
  81. case_data_ids.append(case_uniqueid)
  82. test_data['parameterize'].append(case_data_json)
  83. return test_data, case_data_ids

我把真正的处理 excel 测试用例数据的功能放在了这里,将我们需要的数据,如:url,请求体 data,请求方法 method 等信息组装好,放到内存中,供 pytest 参数化时使用。

3. pytest 测试用例代码

在 case 文件夹中,用来存放真正的 pytest 测试代码,我们写一个简单的测试代码 demo

  1. from base.basetest import BaseTest, CaseData
  2. import pytest
  3. class Test_example(BaseTest):
  4. testcase = CaseData('test.xlsx', 1)
  5. testdata, ids = testcase.get_testcase_data()
  6. @pytest.mark.parametrize('autotest', testdata['parameterize'], ids=ids)
  7. def test_case(self, autotest, casefile):
  8. res_json = self.runmethod.run_main(autotest['request-data']['method'], autotest['request-data']['url'],
  9. data=autotest['request-data']['data'],
  10. header=autotest['request-data']['header'])
  11. print(res_json)
  12. print("casefile", casefile)
  13. assert self.validate.is_equal_dict(res_json, autotest['response-data']['checkpoint']) is True

这里时获取 excel 中的 sheet 序号为1的内容来作为测试数据,如果我们需要把 excel 中所有 sheet 中的数据都作为测试数据来供 pytest 参数化的话,那么就可以实例化 CaseDataAllSheets 类。

4. 测试执行

最后,我们在 main.py 中运行 pytest 主程序

  1. if __name__ == '__main__':
  2. import pytest
  3. pytest.main(['-s', '-q', '-vv', '--html=./report/report.html', '--self-contained-html'])

使用一个 report 插件来自动产生测试报告。

至此,我们以后只需要编写易于操作的 excel,而几乎不需要动任何 Python 代码,就能完成一次接口自动化测试了。当然,编写好的 excel 要放到 data 文件夹下哦!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/821014?site
推荐阅读
相关标签
  

闽ICP备14008679号