• 如何用Python3+requests+unittest实现接口自动化测试实战


    一、Requests介绍

    首先让我们来看 Requests 官方的介绍:

    Requests is an elegant and simple HTTP library for Python, built for human beings.

    翻译过来就是:Requests 是为人类写的一个优雅而简单的 Python HTTP 库。这个介绍很直白了,让我们先来感受一下 Requests 的威力。

    1. import requests
    2. # 发送请求
    3. response = requests.get(url="http://www.baidu.com/s", params={'wd':'python'})
    4. # 处理响应
    5. print(response.status_code)
    6. #返回
    7. 200

     这个请求如果用 urllib 来实现,代码如下:

    1. import urllib.parse
    2. import urllib.request
    3. url = "http://www.baidu.com/s"
    4. params = urllib.parse.urlencode({'wd':'python'})
    5. # 发送请求
    6. response = urllib.request.urlopen('?'.join([url, params]))
    7. # 处理响应
    8. print(response.getcode())
    9. #返回
    10. 200

    从感官上就能看出来,使用 urllib 在 URL 、参数等方面会复杂一些。这只是冰山一角,实际使用中 Requests 还有好多方面超越 urllib ,它并不是浪得虚名,接下来的学习中你就会感受到。

    二、unittest介绍

    说到 Python 的单元测试框架,想必接触过 Python 的朋友脑袋里第一个想到的就是unittest。 的确,作为 Python 的标准库,它很优秀,并被广泛用于各个项目。但你知道吗?其实在 Python 众多项目中,主流的单元测试框架远不止这一个。

    本系列文章将为大家介绍目前流行的 Python 的单元测试框架,讲讲它们的功能和特点并比较其异同,以让大家在面对不同场景、不同需求的时候,能够权衡利弊,选择最佳的单元测试框架。

    三、Python3+requests+unittest

    首先,我们可以捋一捋思路,想一想接口测试的流程

    其次,选择合适的框架

    流程清晰之后,我们需要选择一个合适的框架,于是选择了Python3+requests+unittest框架

    Requests模块发送http的网络请求,请求类型主要包含了post,get, PUT,DELETE,HEAD

    python+unittest单元测试框架构成,和测试报告生成(HTMLTestRunner)

    框架详解不在此赘述,requests可参考

    unittest参考点击查看

    基于以上,我们来一步步搭建我们的框架。在这个过程中,我们需要做到业务和数据的分离,这样才能灵活,达到我们写框架的目的。接下来,我们来进行结构的划分。

    我们的结构是这样的

     

    data:存放自动化测试所用到的数据文档

    log:存放生成的日志文件

    base:存放公共的方法

    report:存放生成的自动化测试报告

    testcase:存放测试脚本

    接下来,公共方法的开发

    整体结构有了划分,接下来就该一步步的填充整个框架了,我们先来看看Base文件中的公共类或函数,这主要用于后续测试case的调用,所有公共的、一成不变的数据都可以放在这里,维护也方便

    配置文档如下

    1. [DATABASE]
    2. data_address = ./data/
    3. report_address = ./report/
    4. [HTTP]
    5. base_url = http://xxx.xx

     想知道怎样从配置文档中得到或写入相应的数据吗?那继续看吧

    1. import os
    2. import configparser
    3. # 获取当前py文件地址
    4. proDir = os.path.split(os.path.realpath(__file__))[0]
    5. # 组合config文件地址
    6. configPath = os.path.join(proDir,"config.ini")
    7. class ReadConfig:
    8. def __init__(self):
    9. #获取当前路径下的配置文件
    10. self.cf = configparser.ConfigParser()
    11. self.cf.read(configPath)
    12. def get_config(self,field,key):
    13. #获取配置文件中的key
    14. result = self.cf.get(field,key)
    15. return result
    16. def set_config(self,field,key,value):
    17. #向配置文件中写入配置信息
    18. fb = open(configPath,'w')
    19. self.cf.set(field,key,value)
    20. self.cf.write(fb)

    那问题又来了,我们的测试数据放在哪里?怎么取值?怎么写入?怎么保存?。。。

    别急,接着往下看

    测试数据优先考虑放在excel或database中,此处以excel为例做个简单介绍

    这里需要用到两个操作表格的库,xlrd数据驱动的读取,作用于excel文档,但xlrd不能写入数据,所以引入xlutils数据驱动的读取和写入

    安装方法可以用pip3 install xlrd和pip3 install xlutils 来安装。

    1. import xlrd
    2. import xlutils.copy
    3. from Base.readConfig import ReadConfig
    4. import time
    5. class ReadExcel:
    6. def __init__(self,section,field,sheet):
    7. # 打开工作表,并定位到sheet
    8. data_address = ReadConfig().get_config(section,field)
    9. workbook = xlrd.open_workbook(data_address)
    10. self.table = workbook.sheets()[sheet]
    11. def get_rows(self):
    12. # 获取excel行数
    13. rows = self.table.nrows
    14. return rows
    15. def get_cell(self,row,col):
    16. # 获取单元格数据
    17. cell_data = self.table.cell(row,col).value
    18. return cell_data
    19. def get_col(self,col):
    20. # 获取整列数据
    21. col_data = self.table.col_value(col)
    22. return col_data
    23. class WriteExcel:
    24. def __init__(self,section,field,sheet):
    25. # 打开工作表
    26. self.address = ReadConfig().get_config(section,field)
    27. self.workbook = xlrd.open_workbook(self.address)
    28. self.wf = xlutils.copy.copy(self.workbook)
    29. self.ws = self.wf.get_sheet(sheet)
    30. def set_cell(self,row,col,value):
    31. #设置单元格数据
    32. self.ws.write(row,col,value)
    33. def save_excel(self,filename,format):
    34. #获取当前时间
    35. self.time = time.strftime("%Y%m%d%H%M%S", time.localtime())
    36. #生成文件的文件名及格式
    37. self.report = filename + '_' +self.time + format
    38. #保存文件
    39. self.wf.save(self.report)

    然后,测试脚本的编辑

    一切准备就绪,下面通过一个简单的、完整的代码进行演示公共函数的调用,框架的使用及报告的生成

    1. import unittest
    2. import requests
    3. from Base.readConfig import ReadConfig
    4. from Base.readExcel import ReadExcel
    5. from Base.readExcel import WriteExcel
    6. #实例化
    7. readexcel = ReadExcel('DATABASE','data_address',0)
    8. writeexcel = WriteExcel('DATABASE','data_address',0)
    9. class testcase(unittest.TestCase):
    10. #初始化
    11. def setUp(self):
    12. #获取url
    13. self.base_url = ReadConfig().get_config('HTTP', 'base_url')
    14. self.url = self.base_url + readexcel.get_cell(1,1)
    15. #获取请求头
    16. self.headers = readexcel.get_cell(1,4)
    17. def test_case(self):
    18. nok = 0
    19. ner = 0
    20. # 循环读取excel中的测试数据,进行结果验证,并生成excel形式的测试报告
    21. for i in range(3,readexcel.get_rows()):
    22. #发送网络请求,得到响应值
    23. response = requests.post(self.url, headers=self.headers, data=readexcel.get_cell(i,4).encode('utf-8'))
    24. actualresult = response.json()
    25. #获取excel中的预期结果
    26. expectresult = eval(readexcel.get_cell(i,6))
    27. # 获取需验证的数据
    28. key = eval(readexcel.get_cell(i, 5))
    29. keylen = len(key)
    30. j = 0
    31. for k in range(keylen):
    32. aresult = 'actualresult' + key[k]
    33. eresult = 'expectresult' + key[k]
    34. if eval(aresult) == eval(eresult):
    35. #预期结果和实际结果一致
    36. j = j + 1
    37. if j == keylen:
    38. #测试数据执行通过
    39. nok = nok + 1
    40. writeexcel.set_cell(i, 8, 'SUCCESS')
    41. else:
    42. # 测试数据执行失败,并将实际结果写入excel
    43. ner = ner + 1
    44. writeexcel.set_cell(i, 8, 'FAILURE')
    45. writeexcel.set_cell(i, 7, str(actualresult))
    46. print('第', i + 1, '行用例执行失败:预期结果是', expectresult, '实际结果是', actualresult)
    47. # 保存测试报告
    48. writeexcel.save_excel('testreport', '.xls')
    49. print('测试数据中总共', nok, '条用例执行通过', ner, '条用例执行失败')
    50. #释放资源
    51. def tearDown(self):
    52. pass
    53. if __name__ == '__main__':
    54. #构造测试集合
    55. suite = unittest.TestSuite()
    56. suite.addTest(testcase('test_case'))
    57. #创建html文件
    58. filename = ReadConfig().get_config('DATABASE', 'report_address') + 'testreport.html'
    59. fb = open(filename,"wb")
    60. #执行测试并生成html测试报告
    61. runner = HTMLTestRunner.HTMLTestRunner(stream = fb,description = '针对接口的描述信息',title = '某某的自动化测试报告')
    62. runner.run(suite)
    63. #关闭文件
    64. fb.close()

    最后,生成的html报告

    感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
     

    这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取 

     

  • 相关阅读:
    vim 实用快捷键
    Kotlin编程实战——协程(08)
    【C语言】为什么建议使用枚举而不是#define?
    Karmada更高效地实现故障转移
    【软件】Ubuntu16.04升级git最新版,升级python到3.7.
    双链笔记软件评测:Roam Research、 Obsidian、Logseq 思源笔记
    springboot:时间格式化的5种方法(解决后端传给前端的时间格式转换问题)推荐使用第4和第5种!
    计算机毕设(附源码)JAVA-SSM基于的装修设计管理系统
    接口测试系列之 —— 前端交互测试和后端逻辑测试
    秋招我借这份PDF的复习思路,收获美团,小米,京东等Java岗offer
  • 原文地址:https://blog.csdn.net/OKCRoss/article/details/134333371