python接口自动化测试 订阅
Python接口自动化测试是2019年电子工业出版社出版的图书。作者是王浩然。 展开全文
Python接口自动化测试是2019年电子工业出版社出版的图书。作者是王浩然。
信息
页    数
232页
作    者
王浩然
定    价
¥59.0
字    数
230千字
书    名
Python接口自动化测试
出版时间
2019-5
开    本
16开
出版社
电子工业出版社
ISBN
9787121356872
Python接口自动化测试内容简介
本书主要介绍如何用Python实现接口自动化测试。全书主要内容包括接口基础、接口手工测试、编程前的准备、用Python处理MySQL数据库、用Python发送HTTP请求、用Python处理HTTP返回包、用Python导出测试数据、接口自动化起航及实际接口场景演示。本书所介绍的方法是作者在实际项目中实践过的,拥有这本书,就拥有了整套的源码。按照本书的环境设置,整套源码是完全可运行的。本书适合初、中级测试工程师,对Python语言感兴趣的人员,以及想要提升技术、突破技术的人员。 [1] 
收起全文
精华内容
下载资源
问答
  • python接口自动化测试

    2018-11-30 10:26:38
    python自动化测试源码,在pycharm中直接运行main.py使用前,阅读README文件,简单易上手
  • Python接接口口自自动动化化测测试试的的实实现现 这篇文章主要介绍了Python接口自动化测试的实现文中通过示例代码介绍的非常详细对大家的学习或者工作 具有一定的 考学习价值需要的朋友们下面随着小编来一起学习...
  • python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口...
  • python接口自动化测试框架结构 ( 第一章) 点击跳转到第一章,你可以知道框架结构!! 前方高能!!正文开始!! 1、在utlis.py封装Excel读写方法 (文件位置跳转第一章看代码结构) 大家需要知道,读取Excel分两种...
  • python接口自动化测试是PDF文档形式,文档中的实现以Python语言为基础,进行HTTP接口自动化框架,模块包括Excel进行参数化,读取配置文件,读取测试用例,执行测试用例,记录...是学习python接口自动化测试的绝佳文档。
  • python接口自动化测试框架---包括请求的封装、数据库操作、多断言、ddt数据驱动、多种请求方式等
  • 测试用例写在excel表格里,通过程序实现自动化运行测试用例,将错误日志打印在log里。是根据一个开源项目改了一些代码,正确填好interface测试用例表格之后就能正常运行。
  • 将通过python+request+unittest+HTMLTestRunner框架进行接口自动化测试,包含有具体的案例,代码。
  • python+request+unittest+HTMLTestRunner 框架,从测试到结果
  • 主要介绍了python接口自动化测试之接口数据依赖的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • python自动化测试框架,使用request,测试数据统一由excel管理,后期维护只需要修改excel中的测试数据,减少的代码的重复改动,提升测试效率
  • 此工具设计初衷是配合 python接口自动化测试框架 而设计的 reader.py 用来读取excel文档,掉用writer中拼接字符串的方法,来生成一个个测试脚本,_init_.py的作用是用来运行HTMLTestRunner,以生成测试报告。比较...
  • 接口自动化测试python源码,都是基于python3 都是基于webdriver,大部分代码都可以通用,只是配置文件不一样 APP监控了常用的men,cpu,fps 数据维护用的YMAL 邮件发送excel的测试报告
  • 接口测试常用的工具有fiddler,postman,jmeter等,使用这些工具测试时,需要了解常用的接口类型和区别,比如我用到的post和get请求,表面上看get用于获取数据post用于修改数据,两者传递参数的方式也有不一样,get...
  • 1.本系统采用Django REST framework编写接口,前端页面采用比较容易上手的vue elementUI 2.初步学习web开发,接口统一采用基于方法的方式编写,后续引入权限系统,并修改成基于类的方法
  • 接口自动化框架 一、首先废话不多说,直接开始讲解一下整个框架的目录结构,本次内容着重讲解测试用例类,只要掌握了测试用例类和接口测试用例怎么写就可以运用此框架。(需要一些python基础,能看的懂基本代码) ...
  • 接口自动化测试.pdf

    2020-08-04 17:30:18
    python+ddt+unittest数据驱动,接口自动化测试框架介绍,用于团队内部培训和技术分享。
  • python接口自动化_YY.pdf

    2019-08-07 09:36:30
    python接口自动化测试教程,适合有Python基础的同学进行接口自动化测试
  • 2019 Python接口自动化测试框架实战开发(一)

    万次阅读 多人点赞 2019-06-28 15:55:25
    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!...整个项目分为四个部分:接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发 接口基础包括:H...

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

    项目源码下载

    目录

    一丶叙述

    二丶接口基础知识

    三丶接口测试工具

    四丶Fiddler的使用

    五丶unittest使用

    六丶mock服务入门到实战

    七丶接口自动化框架设计到开发


    一丶叙述

    1.项目介绍

    整个项目分为四个部分:接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发

    接口基础包括:HTTP接口 / 常见接口 / 接口工具 / 接口基础知识

    接口开发:通过Django来开发get/post接口

    Unittest与接口测试结合:unittest应用 / 断言 / requests引入 / HTMLTestRunner / case的管理

    接口自动化框架从设计到开发:如何设计框架 / 封装工具类 / 重构基类 / 错误调试 / 结果收集以及处理 / 解决数据依赖 / 结果统计及报告发送

    项目整体思路:通过对接口数据文档的读写操作,来获取文档中case的所有数据,然后通过requests模块来发送请求获取的响应数据,通过返回的响应数据中的某个标志性字段的值来判断是否测试成功或者失败,最后将测试的结果数据写入到测试文档或者是html页面又或者是将结果以邮件的形式发送到指定邮箱,这是整个大框架思路,要完成这一系列自动化的测试框架,则需要有一定的python代码基础,博主这里只是粗略的叙述了思路,有很多地方就不细说了比如数据依赖等就请大家慢慢的阅读吧

    2.测试报告效果预览

    • unittest和HTMLTestRunner结合生成报告(新版本的)

    •  unittest和HTMLTestRunner结合生成报告(经典版本的)

    •  测试报告邮件通知

    二丶接口基础知识

    1.什么是接口

    连接前后端以及移动端,通俗来说就是前端和后端之间的桥梁,比如网站需要去调用银行丶微信及支付宝的接口来完成业务需求

    2.接口的种类

    外部接口和内部接口;内部接口又分为上层服务与下层服务以及同级服务

    3.接口的分类

    请求方式:post丶get丶delete丶put

    4.为什么要做接口测试

    原因:不同端的工作进度肯定是不一致的,那么就需要对最开始开发出来的接口进行测试;对于项目来说缩短项目周期,提高开发效率以及提高系统的健壮性

    5.接口测试流程

    需求讨论——需求评审——场景设计——用例设计——数据准备——执行

    6.为什么要设计测试用例

    • 理清思路,避免侧漏
    • 提高测试效率
    • 跟进测试进度
    • 告诉领导做过
    • 跟进重复重复性工作

    7.用例设计分类

    功能用例测试:测试功能是否正常丶测试功能是否按照接口文档实现

    逻辑用例设计:是否存在依赖业务,例如有些操作是需要用户登录成功的状态下才能进行的操作

    异常测试用例设计:参数异常以及数据异常;参数异常包括关键字参数丶参数为空丶多参数丶少参数丶错误参数,数据异常包括关键字数据丶数据为空丶长度不一致丶错误数据

    安全测试用例设计:cookie丶header丶唯一识别码

    三丶接口测试工具

    1.接口测试工具分类

    • 抓取接口工具

    httpwatch:集成于IE和Firefox浏览器中,在其他浏览器中无法使用,查看数据也比较麻烦

    wireshark:只要是经过电脑的所有请求都会去抓取,导致数据量比较庞大,看数据也比较麻烦

    fiddler:轻量级抓包工具,功能比较全,只会记录http请求不会像wireshark工具记录tcp和udp等请求

    • 测试接口工具:

    loadrunner:不仅仅是性能测试工具,由于该工具几乎都是基于http请求,所以也可以用来测试接口

    fiddler:它除了可以抓包还可以向接口发送各种请求

    soapui:接口和自动化测试工具,功能也比较强大

    jmeter:跟loadrunner一样不仅仅是做性能测试,也可以对接口进行测试

    postman:谷歌旗下的接口测试工具

    四丶Fiddler的使用

    1.抓取不同类型接口数据(http以及https)

    • 查看windows本机的IP

    • 配置fiddler

    • 需要保证要抓取的手机与电脑保持同一网段,博主这里使用逍遥模拟器模拟安卓手机,修改手机网络

    • 在高级选项中设置手动代理IP为windows本机IP地址,端口设置与fiddler抓取端口保持一致

    • 再安卓手机中打开知乎app,抓取知乎app的http服务的数据

    • 现在的移动app都是基于https请求的,所以需要在fiddler中设置https请求

    • 然后在手机端浏览器中访问windows电脑IP+port,进行网络安全证书的下载安装

    • 点击下面一个下载证书

    • 然后设置密码即可

    • 证书安装成功后,重新打开知乎app,则成功抓取https请求的数据

    • 在知乎app中随便对一文章进行评论,抓取该app评论接口

    2.数据模拟以及过滤规则

    • 如下图进行选择要过滤的hosts类型,并在输入框添加要过滤的hosts即可

    • 对知乎上的一篇文章进行回答后,获取https://api.zhihu.com/answers接口,查看发送的post请求数据中的content字段内容也就是博主回答的内容

    • 然后进行数据模拟,也就是点击fiddler软件上的replay对https://api.zhihu.com/answers接口进行post请求数据的而二次发送,由于知乎这边设定对一个问题只能进行一次回答,所以知乎服务器返回的json数据提示我们失败,同时也说明对接口进行二次数据发送成功,只是规则逻辑失败

    3.如何模拟接口响应数据

    • 首先第一步,访问知乎app热榜,在fiddler软件中获取接口查看服务器响应的json格式数据,从服务器返回的json数据看出热榜标题字段名为title_area

    • 然后选择服务器返回的数据类型为TextView,点击.View in Notepad即打开数据记事本,如下图在记事本中找到title_area字段的内容,该字段内容进行了将中文转换为一串字符串

    • 将记事本中的title_area字段的数据修改为this is a test for cdtaogang

    • 点击文件——另存为保存到桌面 

    • 回到fiddler中,左侧选中热榜接口,右侧选中AutoResponder,在此窗口下点击Add Rule将左侧的接口添加进去,在右侧下方导入保存在桌面的zhihu_hot.htm文件,最后点击sava保存

    • 回到知乎app中刷新当前热榜页面,则成功返回修改的热榜标题

    4.使用fiddler进行评论接口测试

    • 对一篇文章进行评论,抓取评论接口,因为get请求的接口测试太简单,所以博主这里选择评论接口即POST请求方式

    • 右击评论接口选择copy复制接口的url地址

    • 右侧选择Composer,将复制的评论接口url粘贴到地址栏,并选择POST请求方式

    • 因为评论接口涉及到用户身份验证也就是登录后才能进行评论的,所以需要将comments接口中request headers请求头中的所有请求数据以及请求数据中的TextView的值进行复制

    请求头数据

    请求体数据

    • 将上面复制的请求头和请求体数据分别粘贴到如下输入框中,点击Execute执行发送,然后在左侧则出现了另一个comments接口数据

    • 查看该comments接口,服务器返回的响应数据中与第一个comments接口一致,说明接口测试成功

    五丶unittest使用

    1.unittest简单使用

    • 在IDE中使用python的环境随便创建个py文件,需要注意的是该py文件的名字不能是test.py,否在运行时会出错,unittest包是python自带的不需要下载安装,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/17 13:10'
    
    import unittest
    
    
    class TestMethod(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            print("Method before class execution")
    
        @classmethod
        def tearDownClass(cls):
            print("Method after class execution")
    
        def setUp(self):
            print("------setUp------")
    
        def tearDown(self):
            print("------tearDown------")
    
        def test_01(self):
            print("First test method")
    
        def test_02(self):
            print("The second test method")
    
    
    if __name__ == '__main__':
        unittest.main()
    • 直接run运行以上代码

    2.unittest和request重构封装

    说明:使用requests模块对接口url地址发送请求,通过unittest测试框架进行case测试

    • 首先博主在逍遥安卓模拟器中下载了一个看书app,通过fiddler对app上的某一接口进行获取,之所以选择对此app进行接口测试,是因为该app的所有接口全是POST请求

    • 在PyCharm下新建工程目录,目录下创建base包,在包下创建一个demo.py文件以及test_method.py文件,用于使用unittest框架来测试以上app接口

    • 在demo.py文件中,使用requests get以及post方法进行了封装,主要是根据传递的参数method来对get以及post方法进行分别调用而已,具体实现如下
    import requests
    
    
    class RunMain:
    	def send_get(self,url,data):
    		res = requests.get(url=url,data=data).json()
    		return res
    		
    	def send_post(self,url,data):
    		res = requests.post(url=url,data=data).json()
    		return res
    
    	def run_main(self,url,method,data=None):
    		res = None
    		if method == 'GET':
    			res = self.send_get(url,data)
    		else:
    			res = self.send_post(url,data)
    		return res
    • 在test_method.py文件中则创建测试类以及test方法,在test方法中调用demo.py中的run_main方法,即使用requests模块向传递的接口url地址和请求方式以及请求体发送对应的请求,这里使用setUp方法则是利用其优先调用而对RunMain类进行实例化
    import unittest
    import json
    import HtmlTestRunner
    from .demo import RunMain
    
    
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
    
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 运行test_method模块,查看测试接口,test_02则是错误测试

    3.unittest中assert的使用

    • 首先根据返回的结果字典dict数据中的status状态值来判断测试是否通过或者失败,逻辑很基础就不细说了
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            # print(type(res1))
            # print(res1['pub'])
            # print(type(res1['pub']))
            if res1['pub']['status'] == 0:
                print("测试通过")
            else:
                print("测试失败")
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
            if res2['pub']['status'] == 0:
                print("测试通过")
            else:
                print("测试失败")
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 运行以上代码,查看结果与预期一样

    • 将if判断代码更换成unittest模块中的assert断言进行判断,这里使用assertEqual方法来判断两个值是否相等,当两个值相等则返回OK,当不相同时返回assertEqual方法msg变量自定义的值
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            # print(type(res1))
            # print(res1['pub'])
            # print(type(res1['pub']))
            # if res1['pub']['status'] == 0:
            #     print("测试通过")
            # else:
            #     print("测试失败")
            self.assertEqual(res1['pub']['status'], 0, "测试失败")
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
            # if res2['pub']['status'] == 0:
            #     print("测试通过")
            # else:
            #     print("测试失败")
            self.assertEqual(res2['pub']['status'], 0, "测试失败")
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 测试查看结果,断言失败,测试结果如下很清晰

    4.unittest中case的管理及运用

    • 在测试一些接口时,有些接口的返回数据需要在下一个接口进行使用,所以需要定义全局变量,方便每个case都能够得着,当在test_01中定义全局变量userid,然后在test_02中进行打印

    • 在unittest中,是按照字母数字来进行case先后执行顺序的,将test_01改为test_03后,运行代码后,会提示test_02中的userid未定义,原因是程序先去执行了test_02这个case,所以出现该提示是正常的

    • 当在测试代码中有很多case时,我想跳过某个case,则在该case方法上定义unittest的skip方法装饰器,并需要传递此方法名作为实参进行传递

    • 除了在if __name__ == '__main__'中使用unittest.main方法执行所有的case以外,还可以将要测试的case添加到unittest.TestSuite集合中执行想要执行的case,若想要全部都执行则需要一个一个的添加

    5.unittest和HTMLTestRunner结合生成报告(博主这里给大家展现两种)

    第一种:比较新版本的htmltestrunner报告

    • 然后将下载好的whl文件放在你的项目环境的Scripts目录下

    • 最后在Terminal终端或者cmd终端中进入以上目录,执行如下命令即可

    • 安装成功后,即在以下路径中可以找到安装的HTMLTestRunner的包了

    • 在if __name__ == '__main__'中只需要调用HtmlTestRunner模块中的HtmlTestRunner类,向该类传递报告标题参数值即可,其他均默认,需要注意的时启动文件run为当前的py文件,如果是Unittests开头的启动文件,则不会运行if __name__ == '__main__'下的代码,只会执行unittest框架的setUp以及test开头的case代码

    • 运行test_method.py文件,成功在base目录下创建reports目录,并在该目录下生成对应时间的测试报告

    • 打开reports目录下生成的html测试报告,查看测试内容,与预期设定一样,test_02失败test_03成功,说明一下报告中的乱码为中文

    第二种:比较经典版本的htmltestrunner报告

    • 为了方便演示效果,博主在testItems项目目录下,创建base2的模块,将base模块下的demo.py和test_method.py文件拷贝到base2目录下并将test_method.py命令为test_method2.py免得搞混淆,然后在base2目录下新建HTMLTestRunner.py文件用于存放其源码,目录结构如下

    第94行, 将import StringIO修改成import io
    第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
    第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
    第631行,将print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)修改成print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
    第766行,将uo = o.decode('latin-1')修改成uo = e
    第775行,将ue = e.decode('latin-1')修改成ue = e
    • 在test_method2模块中首先需要从base2模块中去导入HTMLTestRunner文件,然后if __name__ == '__main__'中,需要创建一个文件源,同样是调用HTMLTestRunner模块中的HTMLTestRunner类,不同的是需要将创建的文件源传递给实例属性stream变量

    • 运行test_method2.py,成功在上一级report目录下生成html_report.html报告文件

    • 打开html_report.html测试报告,测试结果与代码设定一致

    六丶mock服务入门到实战

    1.mock简介

    mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为即就是模拟fiddler返回接口响应数据的一个过程。

    2.mock安装

    • 在终端使用pip进行安装即可

    3.在case中通过底层函数实现mock

    • 在test_method模块中导入mock,然后在test_03函数中通过以下代码设置返回的return_value的值为请求的data数据
    mock_data = mock.Mock(return_value=data)
    print(mock_data)
    • run运行Unittests in test_method.py,打印出Mock id的值

    • 将调用run_main方法的值设定为mock_data,即print(res1)则表示打印请求的data数据的值,因为res1的数据不再是接口返回的响应数据,则arrest断言是会提示报错的,这是正常的

    4.重构封装mock服务

    • 在base目录下创建mock_demo.py文件,构造一个mock_test方法,该方法就是将test_03方法中self.run.run_main = mock.Mock(return_value=data) 和 res1 = self.run.run_main(url, "POST", json.dumps(data))方法的调用进行了封装成为test_02和test_03方法通用的一个方法,上一步骤中的代码mock_data = mock.Mock(return_value=data) 和self.run.run_main = mock_data,即就相当于self.run.run_main = mock.Mock(return_value=data)而已,都是python基本的调用封装基础知识,mock_demo.py中的代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/20 16:26'
    from mock import mock
    import json
    
    def mock_test(mock_method, request_data, url, method, response_data):
        """
        :param mock_method:
        :param request_data:
        :param url:
        :param method:
        :param response_data:
        :return: res
        """
        mock_method = mock.Mock(return_value=response_data)
        print('mock_method:', mock_method)
        res = mock_method(url, method, json.dumps(request_data))
        return res
    • 那么在test_03方法中,如下进行调用即可
    res1 = mock_test(self.run.run_main, data, url, 'POST', 'ssssssss')
    print('res1:', res1)
    • 运行Unittests in test_method.py,查看运行结果和博主设定一样成功返回自定义的response_data数据

    七丶接口自动化框架设计到开发

    1.如何设计一个接口自动化测试框架

    根据接口地址丶接口类型丶请求数据丶预期结果来进行设计,对于需要登录后才能进行操作的接口那么则需要进行header cookie等数据的传递,自动化测试的难点就是数据依赖。

    2.python操作excel获得内容

    • 首先python操作excel,需要安装两个包,分别是xlrd和xlwt这两个库,xlrd这个库是负责读取excel数据的,而xlwt库是负责向excel写入数据的

    • 在项目目录下创建utils工具包,在该包下创建op_excel.py文件,在该文件中通过导入xlrd包,对excel表的数据进行读取操作

    3.重构操作excel函数

    • 根据上一步骤读取excel表的内容代码后,进行了一个简单的封装,提高代码的通用性,过程相当的简单,实现代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/20 17:33'
    import xlrd
    
    data = xlrd.open_workbook("../test_data/rs.xls")
    tables = data.sheets()[0]  # 获取表格数据对象
    print(tables.nrows) # 打印表格行数
    print(tables.cell_value(0,0))  # 打印excel表格数据,需要传递数据所在的坐标(x,y)
    print(tables.cell_value(0,1))
    print("*"*50+"封装前后数据对比"+"*"*50)
    
    
    class operationExcel(object):
        def __init__(self, file_path="../test_data/rs.xls", sheet_id=0):
            self.file_path = file_path
            self.sheet_id = sheet_id
            self.data = self.get_data()
    
        def get_data(self):
            data = xlrd.open_workbook(self.file_path)
            tables = data.sheets()[self.sheet_id]
            return tables
    
        def get_rows(self):
            """获取单元格的排数"""
            return self.data.nrows
    
        def get_cell_value(self, x=0, y=0):
            """获取某个单元格的数据"""
            return self.data.cell_value(x, y)
    
    
    if __name__ == '__main__':
        print(operationExcel().get_rows())
        print(operationExcel().get_cell_value())
        print(operationExcel().get_cell_value(0,1))
    • 运行op_excel.py文件后,结果与封装之前代码结果一致,表示重构封装代码成功

    4.学习操作json文件

    • 自定义一个登录的json文件名为login.json,文件内容如下,存放在test_data目录下

    • 在utils工具包下创建op_json.py文件,在文件中对login.json文件内容进行读取操作,代码如下

    5.重构json工具类

    • 将上一步操作json的代码进行封装
    class operationJson(object):
        def __init__(self, file_path="../test_data/login.json"):
            self.file_path = file_path
            self.data = self.get_data()
    
        def get_data(self):
            with open(self.file_path) as f:
                data = json.load(f)
                return data
    
        def get_key_words(self, key=None):
            if key:
                return self.data[key]
            else:
                return self.data
    
    
    if __name__ == '__main__':
        print(operationJson().get_key_words())
        print(operationJson().get_key_words("login"))
        print(operationJson().get_key_words("login")['username'])
    • 运行op_json.py文件,结果与封装之前代码结果一致,表示重构封装代码成功

    6.封装获取常量方法

    • 首先打开excel表格,查看需要获取的字段有哪些

    • 对excel表的字段进行获取,在项目目录下创建名为data的python包,在该包下创建data_conf.py,代码就是简单的获取对应的变量值,具体如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 9:29'
    
    
    class global_var:
        id = '0'  # id
        module = '1'  # 模块
        url = '2'  # url
        run = '3'  # 是否运行
        request_type = '4'  # 请求类型
        request_header = '5'  # 是否携带header
        case_depend = '6'  # case依赖
        response_data_depend = '7'  # 依赖的返回数据
        data_depend = '8'  #  数据依赖
        request_data = '9'  # 请求数据
        expect_result = '10'  # 预期结果
        reality_result = '11'  # 实际结果
    
    
    def get_id():
        return global_var.id
    
    def get_module():
        return global_var.module
    
    def get_url():
        return global_var.url
    
    def get_run():
        return global_var.run
    
    def get_request_type():
        return global_var.request_type
    
    def get_request_header():
        return global_var.request_header
    
    def get_case_depend():
        return global_var.case_depend
    
    def get_response_data_depend():
        return global_var.response_data_depend
    
    def get_data_depend():
        return global_var.data_depend
    
    def get_request_data():
        return global_var.request_data
    
    def get_expect_result():
        return global_var.expect_result
    
    def get_reality_result():
        return global_var.reality_result

    7.封装获取接口数据

    • 在data目录下创建data_get.py文件,在该文件中对excel表数据以及json数据结合上一步封装的常量方法整合后的实现,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 10:01'
    from utils.op_excel import operationExcel
    from utils.op_json import operationJson
    from data import data_conf
    
    class getData(object):
        def __init__(self):
            self.op_excel = operationExcel()
    
        def get_case_lines(self):
            """获取表格行数"""
            return self.op_excel.get_rows()
    
        def get_is_run(self, x):
            """获取case是否运行"""
            flag = None
            y = data_conf.get_run()
            run_value = self.op_excel.get_cell_value(x, y)
            if run_value == 'yes':
                flag = True
            else:
                flag = False
            return flag
    
        def get_is_header(self, x):
            """是否携带header"""
            y = data_conf.get_request_header()
            header = self.op_excel.get_cell_value(x, y)
            if header == 'yes':
                return data_conf.get_header_value()
            else:
                return None
    
        def get_request_method(self, x):
            """获取请求方式"""
            y = data_conf.get_request_type()
            request_method = self.op_excel.get_cell_value(x, y)
            return request_method
    
        def get_request_url(self, x):
            """获取请求地址"""
            y = data_conf.get_url()
            request_url = self.op_excel.get_cell_value(x, y)
            return request_url
    
        def get_request_data(self, x):
            """获取请求数据"""
            y = data_conf.get_request_data()
            request_data = self.op_excel.get_cell_value(x, y)
            if request_data == '':
                return None
            return request_data
    
        def get_data_for_json(self, x):
            """通过excel中的关键字去获取json数据"""
            op_json = operationJson()
            data = op_json.get_key_words(self.get_request_data(x))
            return data
    
        def get_expect_data(self, x):
            """获取预期结果数据"""
            y = data_conf.get_expect_result()
            expect_data = self.op_excel.get_cell_value(x, y)
            if expect_data == '':
                return None
            return expect_data

    8.post、get基类的封装

    • 在base包下创建run_method.py文件,在文件中重新编写对get丶post请求方式的代码封装,具体如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 11:19'
    import requests
    
    
    class RunMain(object):
    
        def get_main(self, url, data=None, header=None):
            res = None
            if header is not None:
                res = requests.get(url=url, data=data, headers=header).json()
            else:
                res = requests.get(url=url, data=data).json()
            return res
    
        def post_main(self, url, data, header=None):
            res = None
            if header is not None:
                res = requests.post(url=url, data=data, headers=header).json()
            else:
                res = requests.post(url=url, data=data).json()
            return res
    
    
        def run_main(self, url, method, data=None, header=None):
            res = None
            if method.lower() == 'post':
                res = self.post_main(url, data, header)
            elif method.lower() == 'get':
                res = self.get_main(url, data, header)
            else:
                return "what ?????"
            return res

    9.主流程封装及错误解决调试

    • 首先在testItems项目目录下新建一个名为main的python包,在该包下创建名为run_test的py文件,该文件为主程序启动文件,代码的逻辑就是将前面封装的方法进行了调用核心就是读取excel表的数据,通过读取到的数据,发送请求,其中包括某一些变量的判断,根据该判断然后到json数据中获取请求的数据,最后就这么的简单,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 11:57'
    from base.run_method import RunMain
    from data.data_get import getData
    
    
    class RunTest(object):
        def __init__(self):
            self.runmain = RunMain()
            self.data = getData()
    
        def run(self):
            res = None
            row_counts = self.data.get_case_lines()  # 获取excel表格行数
            # print(row_counts) 5
            for row_count in range(1, row_counts):
                # print(row_count) 1,2,3,4
                url = self.data.get_request_url(row_count)  # y行不变遍历获取x列的请求地址
                method = self.data.get_request_method(row_count)  # y行不变遍历获取x列的请求方式
                is_run = self.data.get_is_run(row_count)  # y行不变遍历获取x列的是否运行
                data = self.data.get_data_for_json(row_count)  # y行不变遍历获取x列的请求数据,这里面时三次调用,依次分别是get_data_for_json丶get_key_words丶get_request_data
                header = self.data.get_is_header(row_count)
                print('url:', url)
                print('method:', method)
                print('is_run:', is_run)
                print('data:', data)
                print('header:', header)
    
                if is_run:
                    res = self.runmain.run_main(url,method,data,header)
                    print("*"*60+"分割线"+"*"*60)
            return res
    
    
    if __name__ == '__main__':
        print('res:', RunTest().run())
    • 运行run_test,成功的将excel以及json数据正确打印出来,返回res服务器返回结果,需要说明的是excel表中的所有数据都不是真实存在的,包括json文档数据也是,这里主要是测试整个框架的正确性读取excel以及json文档数据,并正确的发送请求获得相应数据

    • 运行结果出现红色的内容,是由requests模块发送请求的安全请求警告,如不想显示此警告,可以在run_method.py发送请求核心代码进行禁用,禁用代码如下

    • 重新运行run_test,安全请求警告不再显示

    • 根据代码运行结果,对比excel表以及json数据文档内容,数据正确无误

    10. 返回数据格式处理以及调错

    • 为了测试返回的接口的响应数据,博主这里在excel文档以及json文档中添加了一条数据

    • 因为在excel文档中小说的接口不携带header所以在向接口发送请求数据核心代码块,进行了如下修改,因为在excel文档中的最后一个接口时真实的,所以只需要对最后一个接口url返回的字典类型的响应数据进行转换成json格式的数据,并按照关键字进行排序

    • 运行run_test,在最后一个接口中成功打印出我们想要的数据

    11.获取接口返回状态

    • 在发送请求数据核心代码中,进行打印返回的状态码status_code即可,最后一个接口比较特殊,返回的响应数据中没有status_code,所以需要对返回的json数据中的status进行判断,并向其返回数据中添加我们所要的status_code的值

    • 运行代码,当返回的状态码为404表示接口不存在,只要是存在响应数据,则status_code为200,必须说明一点的就是status_code为200不一定表示接口存在,有些大型网站会对其域名下不存在的接口返回200的错误页面显示,所以在测试文档中会体现预期结果和实际结果两项数据需要一致才能表示测试通过

    12.通过预期结果判断case是否执行成功

    • 进行接下来的测试,博主这里重新准备了另一个excel表来进行测试,需要对json文件中的数据进行添加,在excel表Book-05中的请求数据book5关键字对应的json文件的数据故意为空,可以对测试结果有一个对比

    • 在数据获取核心类中定义了一个方法来获取excel表模块字段的数据

    • 回过头在启动文件中获取模块名预期结果并进行打印

    • 运行启动文件,查看运行结果

    • 在utils目录下,创建common_util.py文件,在该文件代码中通过启动文件传递过来的数据来判断excel表预期结果数据的status状态码与res结果中的status状态码是否一致,一致表示测试通过,不一致则失败,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 18:43'
    import json
    
    class CommonUtil(object):
        def is_contains(self, expect, reality):
            flag = None
            reality = json.loads(reality)
            expect = json.loads(expect)
            if expect['status'] == reality['pub']['status']:
                flag = True
            else:
                flag = False
            return flag
    • 在启动文件中需要注释掉res响应数据,利于查看测试结果,还需要在启动文件调用is_contains方法来根据其返回值判断测试是否通过

    • 运行启动文件,查看测试结果

    13.将测试结果写入到excel中

    • 首先在op_excel.py中定义一个方法,该方法实现读取excel的数据,并进行copy复制,然后再write方法将数据写入到坐标位置

    • 然后在data_get.py中需要定义一个方法,在该方法中核心逻辑为获取y坐标的值

    • 最后在启动文件中,调用data_get模块中的write_reality_data方法,并将剩余的x坐标的值以及data数据传递给最终的核心方法write_reality_result_data来完成对excel表中的实际结果数据的写入

    • 将excel表进行关闭后,运行启动文件,再次打开excel表,实际结果数据写入正确,之所以需要关闭excel是避免提示提示错误,无法写入保存数据

     

    展开全文
  •  接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当工具不太适合...

    更多教程请到:菜鸟教程 https://www.piaodoo.com/

    1)环境准备:

      接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当工具不太适合项目时需要自己进行开发。

      在我们项目的初期,我们采用的是jmeter进行接口测试,当时觉得这个工具上手简单,团队成员学习成本低,并且接口测试的脚本稍微调整一下还可以用来做性能测试。

      不过随着项目规模、团队人数的不断增长,渐渐的这个工具有适应不了当前项目的需求了,为此我们项目也重新开发了相关接口自动化的平台。但是,但是。。。可能是我让大家中毒太深,现在很多同学一提到接口测试关联到jmeter,为此,我深深感到不安。毕竟jmeter只是个工具,换个项目换个协议你是否还能玩转接口测试呢?session和cookie有什么区别?工具又是怎么实现的呢?

      比如session如何保存,接口依赖如何处理,case如何管理及执行顺序,测试数据如何管理等等题,这个过程也有助于我们更加深刻的理解接口测试和http协议。

      本文主要采用python语言,python中http协议接口相关的库有urllib,urllib2以及reqeusts库,这其中reqeusts库用来起来最方便,因此我也主要采用requests库来做http协议的接口测试。首先来看下需要哪些环境信息:

    一、安装python

      mac下自带安装了python,这个不多说了。

    二、安装虚拟环境:

    我们在一台机器上可以安装多个python版本,为了使每个版本的环境相互不受干扰,可以安装虚拟环境,安装方法如下:

    1、安装virtualenv:pip install virtualenv

    2、新建名为venv的虚拟环境:virtualenv venv

    3、进入新环境:source venv/bin/activate

    4、退出:deactivate

    三、安装requests库

    >>>pip install requests

    ps:用python做http协议的接口测试会用到这个库。

    四、http测试工具:

    一个使用 Python + Flask 编写的 HTTP 请求和响应服务,该服务主要用于测试 HTTP 库。后续测试我们都基于这个网站。

    http://httpbin.org

    五、在本地搭建httpbin:

    考虑到测试时要不断访问 httpbin 网站,请求过多担心被拉到黑名单,我们自己在本志搭建一套httpbin服务。

    1、安装:pip install gunicorn

    2、安装:pip install httpbin

    3、启动:gunicorn httpbin:app

    至此,环境搭建已经完毕,可以开始玩了~

    (2)requests.get()

    环境搭建好后,接下来我们先来了解一下requests的一些简单使用,主要包括:

    requests常用请求方法使用,包括:get,postrequests库中的Session、Cookie的使用其它高级部分:认证、代理、证书验证、超时配置、错误异常处理等。

    本节首先来了解一下requests库中如何发送get请求:

    一、看下方法定义:

    1、到官方文档去了下requests.get()方法的定义,如下:

    2、点击右上角的【source】,看一下它的源码如下:

    看到最后一行return,get方法最后是通过调用 requests.request方法实现的,其实在其它的请求方法如post,put,head,delete等方法都是调用的request方法,然后把请求方法的类型传递给request方法第一个参数。

    3、HTTP协议是一个基于请求/响应模式的、无状态的,应用层协议。既然有请求,就有响应,来看下resquest中常用的响应信息:

    二、get方法简单使用:

    1、不带参数的get:

    # -*- coding:utf-8 -*-
    #不带参数的get
    

    import requests
    import json

    host = “http://httpbin.org/”
    endpoint = “get”

    url = ‘’.join([host,endpoint])
    r = requests.get(url)
    #response = r.json()

    print type(r.text)
    print (eval(r.text))

    输出:

    {
      'origin': '183.14.133.88',
      'headers': {
        'Connection': 'close',
        'Host': 'httpbin.org',
        'Accept-Encoding': 'gzip,
        deflate',
        'Accept': '*/*',
        'User-Agent': 'python-requests/2.18.1'
      },
      'args': {
    

    },
    ‘url’: ‘http: //httpbin.org/get’
    }

    2、 带参数的get:

    # -*- coding:utf-8 -*-
    #带参数的get
    

    import requests
    import json

    host = “http://httpbin.org/”
    endpoint = “get”

    url = ‘’.join([host,endpoint])
    params = {“show_env”:“1”}
    r = requests.get(url=url,params=params)

    print r.url

    输出:

    http://httpbin.org/get?show_env=1
    {
      'origin': '183.14.133.88',
      'headers': {
        'X-Request-Id': 'ebe922b4-c463-4fe9-9faf-49748d682fd7',
        'Accept-Encoding': 'gzip,
        deflate',
        'X-Forwarded-Port': '80',
        'Total-Route-Time': '0',
        'Connection': 'close',
        'Connect-Time': '0',
        'Via': '1.1vegur',
        'X-Forwarded-For': '183.14.133.88',
        'Accept': '*/*',
        'User-Agent': 'python-requests/2.18.1',
        'X-Request-Start': '1504755961007',
        'Host': 'httpbin.org',
        'X-Forwarded-Proto': 'http'
      },
      'args': {
        'show_env': '1'
      },
      'url': 'http: //httpbin.org/get?show_env=1'
    }

    3、带header的get:

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

    import requests
    import json

    host = “http://httpbin.org/”
    endpoint = “get”

    url = ‘’.join([host,endpoint])
    headers = {“User-Agent”:“test request headers”}

    r = requests.get(url)
    r = requests.get(url,headers=headers)
    #response = r.json()
    print (eval(r.text))[‘headers’][‘User-Agent’]

    输出:

    test request headers

    4、同时带参数和header:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “get”

    url = ‘’.join([host,endpoint])
    headers = {“User-Agent”:“test request headers”}
    params = {“show_env”:“1”}

    r = requests.get(url)
    r = requests.get(url,headers=headers,params=params)

    #response = r.json()
    print (eval(r.text))[‘headers’][‘User-Agent’]
    print r.url

    输出:

    test request headers
    http://httpbin.org/get?show_env=1

    (3)requests.post()

    一、方法定义

    二、post方法简单使用

      1、带数据的post

      2、带header的post

      3、带json的post

      4、带参数的post

      5、普通文件上传

      6、定制化文件上传

      7、多文件上传

    一、方法定义:

    1、到官方文档去了下requests.post()方法的定义,如下:

    2、源码:

    3、常用返回信息:

    二、post方法简单使用:

    1、带数据的post:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”
    url = ‘’.join([host,endpoint])
    data = {‘key1’:‘value1’,‘key2’:‘value2’}

    r = requests.post(url,data=data)
    #response = r.json()
    print (r.text)

    输出:

    {
     "args": {}, 
     "data": "", 
     "files": {}, 
     "form": {
      "key1": "value1", 
      "key2": "value2"
     }, 
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Content-Length": "23", 
      "Content-Type": "application/x-www-form-urlencoded", 
      "Host": "httpbin.org", 
      "User-Agent": "python-requests/2.18.1"
     }, 
     "json": null, 
     "origin": "183.14.133.88", 
     "url": "http://httpbin.org/post"
    }

    2、带header的post:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    headers = {“User-Agent”:“test request headers”}

    r = requests.post(url)

    r = requests.post(url,headers=headers)
    #response = r.json()

    输出:

    {
     "args": {}, 
     "data": "", 
     "files": {}, 
     "form": {}, 
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Content-Length": "0", 
      "Host": "httpbin.org", 
      "User-Agent": "test request headers"
     }, 
     "json": null, 
     "origin": "183.14.133.88", 
     "url": "http://httpbin.org/post"
    }

    3、带json的post:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    data = {
    “sites”: [
    { “name”:“test” , “url”:“www.test.com” },
    { “name”:“google” , “url”:“www.google.com” },
    { “name”:“weibo” , “url”:“www.weibo.com” }
    ]
    }

    r = requests.post(url,json=data)

    r = requests.post(url,data=json.dumps(data))

    response = r.json()

    输出:

    {
     "args": {}, 
     "data": "{\"sites\": [{\"url\": \"www.test.com\", \"name\": \"test\"}, {\"url\": \"www.google.com\", \"name\": \"google\"}, {\"url\": \"www.weibo.com\", \"name\": \"weibo\"}]}", 
     "files": {}, 
     "form": {}, 
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Content-Length": "140", 
      "Content-Type": "application/json", 
      "Host": "httpbin.org", 
      "User-Agent": "python-requests/2.18.1"
     }, 
     "json": {
      "sites": [
       {
        "name": "test", 
        "url": "www.test.com"
       }, 
       {
        "name": "google", 
        "url": "www.google.com"
       }, 
       {
        "name": "weibo", 
        "url": "www.weibo.com"
       }
      ]
     }, 
     "origin": "183.14.133.88", 
     "url": "http://httpbin.org/post"
    }

    4、带参数的post:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    params = {‘key1’:‘params1’,‘key2’:‘params2’}

    r = requests.post(url)

    r = requests.post(url,params=params)
    #response = r.json()
    print (r.text)

    输出:

    {
    "args": {
    "key1": "params1",
    "key2": "params2"
    },
    "data": "",
    "files": {},
    "form": {},
    "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Connection": "close",
    "Content-Length": "0",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.18.1"
    },
    "json": null,
    "origin": "183.14.133.88",
    "url": "http://httpbin.org/post?key2=params2&key1=params1"
    }

    5.普通文件上传:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    #普通上传
    files = {
    ‘file’:open(‘test.txt’,‘rb’)
    }

    r = requests.post(url,files=files)
    print (r.text)

    输出:

    {
     "args": {}, 
     "data": "", 
     "files": {
      "file": "hello world!\n"
     }, 
     "form": {}, 
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Content-Length": "157", 
      "Content-Type": "multipart/form-data; boundary=392865f79bf6431f8a53c9d56c62571e", 
      "Host": "httpbin.org", 
      "User-Agent": "python-requests/2.18.1"
     }, 
     "json": null, 
     "origin": "183.14.133.88", 
     "url": "http://httpbin.org/post"
    }

    6.定制化文件上传:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    #自定义文件名,文件类型、请求头
    files = {
    ‘file’😦‘test.png’,open(‘test.png’,‘rb’),‘image/png’)
    }

    r = requests.post(url,files=files)
    print (r.text)heman793

    7.多文件上传:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])
    #多文件上传
    files = [
    (‘file1’,(‘test.txt’,open(‘test.txt’, ‘rb’))),
    (‘file2’, (‘test.png’, open(‘test.png’, ‘rb’)))
    ]

    r = requests.post(url,files=files)
    print (r.text)

    8.流式上传:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “post”

    url = ‘’.join([host,endpoint])

    #流式上传
    with open( ‘test.txt’ ) as f:
    r = requests.post(url,data = f)

    print (r.text)

    输出:

    {
     "args": {}, 
     "data": "hello world!\n", 
     "files": {}, 
     "form": {}, 
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Content-Length": "13", 
      "Host": "httpbin.org", 
      "User-Agent": "python-requests/2.18.1"
     }, 
     "json": null, 
     "origin": "183.14.133.88", 
     "url": "http://httpbin.org/post"
    }

    (4)Cookie&Session

    掌握了前面几节的的内容,就可以做一些简单的http协议接口的请求发送了,但是这些还不够。HTTP协议是一个无状态的应用层协议,也就是说前后两次请求是没有任何关系的,那如果我们测试的接口之前有相互依赖关系怎么办呢(比如我要在博客园发文章,是需要先登录的),这时我们就要用到cookie和session技术来保持客户端与服务器端连接的状态,这也就是本节要介绍的内容:

    一、Cookie:

    1、获取cookie:

    # -*- coding:utf-8 -*-
    #获取cookie
    import requests
    import json
    

    url = “https://www.baidu.com/”
    r = requests.get(url)

    #将RequestsCookieJar转换成字典
    c = requests.utils.dict_from_cookiejar(r.cookies)

    print r.cookies
    print c

    for a in r.cookies:
    print a.name,a.value

    输出:

    <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
    {'BDORZ': '27315'}
    BDORZ 27315

    2、发送Cookie

    # -*- coding:utf-8 -*-
    #发送cookie到服务器
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “cookies”

    url = ‘’.join([host,endpoint])
    #方法一:简单发送

    cookies = {“aaa”:“bbb”}

    r = requests.get(url,cookies=cookies)

    print r.text

    #方法二:复杂发送
    s = requests.session()
    c = requests.cookies.RequestsCookieJar()
    c.set(‘c-name’,‘c-value’,path=’/xxx/uuu’,domain=’.test.com’)
    s.cookies.update©

    二、Session

    1、保持会话同步:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “cookies”

    url = ‘’.join([host,endpoint])
    url1 = “http://httpbin.org/cookies/set/sessioncookie/123456789”

    r = requests.get(url)
    print r.text

    print “------”

    s = requests.session() #初始化一个session对象
    s.get(url1) #cookie的信息存在了session中
    r = s.get(url)

    print r.text

    输出:

    {
     "cookies": {}
    }
    

    {
    “cookies”: {
    “sessioncookie”: “123456789”
    }
    }

    2、保存绘画信息:

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “headers”

    url = ‘’.join([host,endpoint])

    header1 = {“testA”:“AAA”}
    header2 = {“testB”:“BBB”}

    s = requests.session() #初始化一个session对象
    s.headers.update(header1) #已经存在于服务中的信息
    r = s.get(url,headers=header2) #发送新的信息

    print r.text

    输出:

    {
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Host": "httpbin.org", 
      "Testa": "AAA", 
      "Testb": "BBB", 
      "User-Agent": "python-requests/2.18.1"
     }
    }

    3.删除已存在的会话信息,保存为None

    # -*- coding:utf-8 -*-
    import requests
    import json
    

    host = “http://httpbin.org/”
    endpoint = “headers”

    url = ‘’.join([host,endpoint])

    header1 = {“testA”:“AAA”}
    header2 = {“testB”:“BBB”}

    s = requests.session() #初始化一个session对象
    s.headers.update(header1) #已经存在于服务中的信息
    r = s.get(url,headers=header2) #发送新的信息

    print r.text

    print ‘--------’

    s.headers[‘testA’] = None #删除会话里的信息testA
    r1 = s.get(url,headers = header2)
    print r1.text

    {
     "headers": {
      "Accept": "*/*", 
      "Accept-Encoding": "gzip, deflate", 
      "Connection": "close", 
      "Host": "httpbin.org", 
      "Testa": "AAA", 
      "Testb": "BBB", 
      "User-Agent": "python-requests/2.18.1"
     }
    }
    

    {
    “headers”: {
    “Accept”: “/”,
    “Accept-Encoding”: “gzip, deflate”,
    “Connection”: “close”,
    “Host”: “httpbin.org”,
    “Testb”: “BBB”,
    “User-Agent”: “python-requests/2.18.1”
    }
    }

    4、提供默认数据:

    s = requests.Session()
    s.auth = ('user', 'pass')
    s.headers.update({'x-test': 'true'})
    

    both ‘x-test’ and ‘x-test2’ are sent

    s.get(‘http://httpbin.org/headers’, headers={‘x-test2’: ‘true’})

    参考:

    http://docs.python-requests.org/en/master/user/quickstart/#cookies
    http://docs.python-requests.org/en/master/user/advanced/#session-objects

    (5)其他(认证&代理&超时设置)

    一、认证

    1、基本认证:

    # -*- coding:utf-8 -*-
    import requests
    

    url = “http://httpbin.org/basic-auth/user/passwd”

    r1 = requests.get(url)
    print “未提供用户名密码:” + str(r1.status_code)

    #Basic Authentication
    r2 = requests.get(url,auth=(‘user’,‘passwd’))
    print “已提供用户名密码:” + str(r2.status_code)

    输出:

    未提供用户名密码:401
    已提供用户名密码:200

    2、数字认证:

    >>> from requests.auth import HTTPDigestAuth
    >>> url = 'http://httpbin.org/digest-auth/auth/user/pass'
    >>> requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
    <Response [200]>

    3、OAuth认证:

      参考:http://docs.python-requests.org/en/master/user/authentication/

    二、代理

    1、方法一:proxy参数:

    import requests
    

    proxies = {
    “https”: “http://41.118.132.69:4433”
    }
    r = requests.post(“http://httpbin.org/post”, proxies=proxies)
    print r.text

    2、方法二:设置环境变量:

    $ export HTTP_PROXY="http://10.10.1.10:3128"
    $ export HTTPS_PROXY="http://10.10.1.10:1080"
    

    $ python
    >>> import requests
    >>> requests.get(‘http://example.org’)

    3、HTTP Basic Auth使用代理方法:http://user:password@host/

    proxies = {'http': 'http://user:pass@10.10.1.10:3128/'}

    三、证书验证

    1、SSL证书(HTTPS):

    import requests
    

    #跳过12306 的证书验证,把 verify 设置为 False:
    r = requests.get(‘https://kyfw.12306.cn/otn/’, verify=False)
    print r.text

    2、客户端证书:

    >>> requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key'))
    <Response [200]>

    or

    s = requests.Session()
    s.cert = '/path/client.cert'

    四、超时配置

    1 、利用timeout参数来配置最大请求时间:

    r = requests.get('https://github.com', timeout=5)

    2、设置timeout=None,告诉请求永远等待响应,而不将请求作为超时值传递

    r = requests.get('https://github.com', timeout=None)

    五、错误异常

    1、所有Requests显式抛出的异常都继承自:requests.exctptions.RequestException

    2、遇到网络问题(如:DNS查询失败,拒绝连接等)时,requests会抛出一个ConnectionError异常

    3、遇到罕见的无效HTTP响应时,Request则会抛出一个HTTPError异常

    4、若请求超时,则抛出一个Timeout异常

    5、若请求超过了最大的重写向次数,则会抛出一个TooManyRedirects异常

    (6)unittest-单个用例管理:

    上面主要介绍了环境搭建和requests库的使用,可以使用这些进行接口请求的发送。但是如何管理接口案例?返回结果如何自动校验?这些内容光靠上面五节是不行的,因此从本节开始我们引入python单元测试框架 unittest,用它来处理批量用例管理,校验返回结果,初始化工作以及测试完成后的环境复原工作等等。

    一、单个用例管理起来比较简单,参考如下图,单个用例一般多用在调试的时候:

    二、代码如下:

    # -*- coding:utf-8 -*-
    # 单个用例执行
    # 1、导入模块
    import unittest
    

    2、继承自unittest.TestCase类

    class TestOne(unittest.TestCase):

    3、配置环境:进行测试前的初始化工作

    def setUp(self):
    print ‘\ncases before’
    pass

    4、定义测试用例,名字以“test”开头

    def test_add(self):
    ‘’‘test add method’’’
    print ‘add…’
    a = 3 + 4
    b = 7
    # 5、定义assert断言,判断测试结果
    self.assertEqual(a, b)

    def test_sub(self):
    ‘’‘test sub method’’’
    print ‘sub…’
    a = 10 - 5
    b = 4
    self.assertEqual(a, b)

    6、清理环境

    def tearDown(self):
    print ‘case after’
    pass

    7、该方法会搜索该模块下所有以test开头的测试用例方法,并自动执行它们

    if name == ‘main’:
    unittest.main()

    输出:

    Ran 2 tests in 0.001s
    OK
    

    cases before
    add…
    case after

    cases before
    sub…
    case after

    Process finished with exit code 0

    (8)unittest-生成测试报告:

    用例的管理问题解决了后,接下来要考虑的就是报告我问题了,这里生成测试报告主要用到HTMLTestRunner.py 这个模块,下面简单介绍一下如何使用:

    一、下载HTMLTestRunner下载:

    这个模块不能通过pip安装,只能下载安装,下载地址如下:

    python2.x版本:http://tungwaiyip.info/software/HTMLTestRunner.html

    python3.x版本:http://hzqldjb.blog.51cto.com/9587820/1590802

    二、mac下配置

    1、终端进入python环境

    2、输入:

    import sys
    print sys.path

    3、找到site-packages文件夹的路径并将下载的HTMLTestRunner.py文件拷贝到此的文件夹下

    4、在python环境下,输入 import HTMLTestRunner 不报错即安装成功

    三、使用该模块生成报告:

    1、目录结构

    • case包下面有baidu,httpbin两个包
    • 每个包下面分别有两个测试的py文件
    • 每个test_00x.py文件里各有2个test case
    • run_all_case.py文件:用来执行所有的test case且生成测试报告

    2、运行后生成报告如下:

    3、run_all_case.py代码如下:

    # -*- coding:utf-8 -*-
    import unittest
    import os
    import time
    import HTMLTestRunner
    

    用例路径

    case_path = os.path.join(os.getcwd())

    报告存放路径

    report_path = os.path.join(os.getcwd(), ‘report’)
    print report_path

    def all_case():
    discover = unittest.defaultTestLoader.discover(case_path, pattern=“test*.py”, top_level_dir=None)

    print discover
    return discover

    if name == ‘main’:

    1、获取当前时间,这样便于下面的使用。

    now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))

    2、html报告文件路径

    report_abspath = os.path.join(report_path, “result_”+now+".html")

    3、打开一个文件,将result写入此file中

    fp = open(report_abspath, “wb”)
    runner = HTMLTestRunner.HTMLTestRunner(stream=fp,
    title=u’接口自动化测试报告,测试结果如下:’,
    description=u’用例执行情况:’)

    4、调用add_case函数返回值

    runner.run(all_case())
    fp.close()

    到此这篇关于Python接口自动化测试的实现的文章就介绍到这了,更多相关Python接口自动化测试内容请搜索菜鸟教程www.piaodoo.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持菜鸟教程www.piaodoo.com!

    展开全文
  • 2.caseName="case"这个 case 是存放测试用例的文件夹,如果没有的话,自动创建。如果想运行其它文 件夹的用例,就改下 caseName 这个参数值 3.rule="test*.py"这个是匹配用例脚本名称的规则,默认匹配 test 开头的...
  • python接口自动化测试视频教程全集下载地址:https://k.weidian.com/Pfm=DyuI课程内容:第一章:接口测试基础1-1 接口自动化课程简介1-2 接口测试课程大纲1-3 接口测试概述1-4 HTTP简介1-5 HTTP功能与特点1-6 HTTP...

    python接口自动化测试视频教程全集

    下载地址:https://k.weidian.com/Pfm=DyuI

    课程内容:

    第一章:接口测试基础

    1-1 接口自动化课程简介

    1-2 接口测试课程大纲

    1-3 接口测试概述

    1-4 HTTP简介

    1-5 HTTP功能与特点

    1-6 HTTP请求方法

    1-7 HTTP请求头与请求URL

    1-8 HTTP请求体

    1-9 HTTP响应

    1-10 JSON简介

    1-11 JSON数据解析

    第二章:接口测试工具—Postman

    2-1 Postman简介

    2-2 Postman请求发送—GET

    2-3 Postman请求发送—POST

    2-4 Postman请求发送—PUT&DELETE

    2-5 Postman接口授权设置(1)

    2-6 Postman接口授权设置(2)

    2-7 Postman Cookie设置

    2-8 Postman 环境变量

    2-9 Postman本地变量

    2-10 Postman全局变量&数据变量

    2-11 Postman断言

    2-12 批量执行&数据驱动

    2-13 Postman构建工作流

    2-14 Postman命令执行

    2-15 Postman jenkins集成

    第三章:接口测试工具—Jmeter

    3-1 Jmeter简介

    3-2 Jmeter发送请求

    3-3 Jmeter断言

    3-4 Jmeter 参数设置

    3-5 用户变量&函数变量

    3-6 Beanshell变量

    3-7 CSV数据文件变量&参数化

    3-8 正则匹配

    3-9 用例数据分离

    3-10 Cookie设置

    3-11 授权设置

    3-12 测试报告

    3-13 Jmeter接口自动化测试平台(1)

    3-14 Jmeter接口自动化测试平台(2)

    第四章:Python接口测试

    4-1 Requests库简介

    4-2 Requests发送HTTP请求

    4-3 Requests 参数传递

    4-4 Requests请求头设置

    4-5 Requests Cookies设置

    4-6 Requests 超时设置&文件上传

    4-7 Requests 会话对象

    4-8 Requests SSL验证&代理设置

    4-9 Requests 身份认证

    4-10 Requests 流式请求

    4-11 Python接口测试实践——基于天气API(1)

    4-12 Python接口测试实践——基于天气API(2)

    4-13 Pyhton接口测试实践—unittest用例封装(1)

    4-14 Pyhton接口测试实践—unittest用例封装(2)

    4-15 Pyhton接口测试实践—测试报告生成

    第五章:Restful接口开发与测试

    5-1 Rest概述

    5-2 Django安装&项目创建

    5-3 Django数据库配置&服务启动

    5-4 Django视图创建

    5-5 Django URL路由配置

    5-6 Django API编辑

    5-7 Swagger接口文档生成(1)

    5-8 Swagger接口文档生成(2)

    5-9 Restful接口测试—Postman

    5-10 Restful接口测试—Python(1)

    5-11 Restful接口测试—Python(2)

    5-12 Django数据管理—Mysql配置

    5-13 Django数据管理—数据库迁移

    5-14 Django数据管理—封装初始化操作(1)

    5-15 Django数据管理—封装初始化操作(2)

    5-16 Django数据管理—封装初始化数据

    5-17 Django数据管理—测试用例封装

    5-18 Django数据管理—执行用例&测试报告

    5-19 Restful接口测试—日志捕捉配置

    5-20 Restful接口测试—Jenkins集成

    5-21 Locust接口性能测试(1)

    5-22 Locust接口性能测试(2)

    5-23 Locust接口性能测试—参数化

    5-24 Locust接口性能测试—运行模式

    5-25 本章小结

    第六章:Mock工具—Json Server

    6-1 Json Server简介

    6-2 Json Server入门使用

    6-3 Json Server接口调试

    6-4 Json Server接口调试

    第七章:HttpRunner接口自动化框架

    7-1 HttpRunner简介

    7-2 HttpRunner入门使用

    7-3 HttpRunnerManager简介

    7-4 HttpRunnerManager配置启动

    7-5 HttpRunnerManager入门使用

    7-6 请求参数与Header配置

    7-7 断言设置&用例组合

    7-8 测试套件&定时任务

    7-9 配置管理—公共变量配置

    7-10 配置管理—参数化配置(1)

    7-11 配置管理—参数化配置(2)

    7-12 进阶应用—自定义辅助函数

    7-13 进阶应用—Hook机制

    7-14 接口测试面试题

    7-15 课程小结

    展开全文
  • 基于python接口自动化测试框架讲解用PPT,为了能让学员更好的理解接口自动化测试框架的PPT。
  • 主要介绍了Python接口自动化测试的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Python接口自动化测试教程.part1 第一步峰 内置播放器
  • python 接口自动化测试-----常见面试题汇总

    千次阅读 多人点赞 2020-09-21 10:47:59
    1、软件接口是什么? 程序不同模块之间传输数据并作处理的类或函数 2、HTTP 和 HTTPS 协议区别? 答: https 协议需要到 CA(Certificate Authority,证书颁发机构)申请证书,一般免费证书 较少,因而需要一定费用...

    1、软件接口是什么?

    程序不同模块之间传输数据并作处理的类或函数

    2、HTTP 和 HTTPS 协议区别?

    答: https 协议需要到 CA(Certificate Authority,证书颁发机构)申请证书,一般免费证书 较少,因而需要一定费用; http 是超文本传输协议,信息是明文传输,Https 协议是由 SSL+Http 协议构建的可进行加 密传输、身份认证的网络协议,比 http 协议安全; http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443;

    3.HTTPS 在哪一层?

    以前我面试很喜欢提网络协议的问题,有朋友说我装 X,不实用。稍有点研究网络知识,实 际就不难回答
    答:HTTPS 在应用层
    在这里插入图片描述

    4、get 和 post 区别是什么?

    答:POST 和 GET 都是向服务器提交数据,并且都会从服务器获取数据。 区别: 1)传送方式:get 通过地址栏传输,post 通过报文传输 2)传送长度:get 参数有长度限制(受限于 url 长度),而 post 无限制 3)GET 产生一个 TCP 数据包(对于 GET 方式的请求,浏览器会把 http header 和 data 一并 发送出去,服务器响应 200 返回数据),POST 产生两个 TCP 数据包(对于 POST,浏览器先 发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok 返回数 据) 4)get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留 5)在做数据查询时,建议用 GET 方式;而在做数据添加、修改或删除时,建议用 post 方式

    5、常见的 POST 提交数据方式

    答: 主要有四种方式:application/x-www-form-urlencoded、multipart/form-data、 application/json、text/xml 等。

    6、什么是 Http 协议无状态协议?怎么解决 HTTP 协议无状态协议

    答: 无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服 务器发送 HTTP 请求之后,服务器根据请求,会给我们发送数据过来,但是,发送完,不会 记录任何信息。HTTP 是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive 没能 改变这个结果。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导 致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。HTTP 协议这种特性有优点也有缺点,优点在于解放了服务器,每一次请求“点到为止”不会造成 不必要连接占用,缺点在于每次请求会传输大量重复的内容信息。客户端与服务器进行动态 交互的 Web 应用程序出现之后,HTTP 无状态的特性严重阻碍了这些应用程序的实现,毕竟 交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是, 两种用于保持 HTTP 连接状态的技术就应运而生了,一个是 Cookie,而另一个则是 Session。

    7、cookie 和 session 的区别

    答: cookie 数据存放在客户的浏览器上,session 数据放在服务器上 cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗,考虑到安全 应当使用 session session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑 到减轻服务器性能方面应当使用 cookie 单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie 可以将登陆信息等重要信息存放为 session;其他信息需要保存,可以放在 cookie

    8、请求接口中常见的返回状态码

    答:
    1xx – 信息提示(表示临时的响应。客户端在收到常规响应之前,准备接收一个或多个 1xx 响应)
    2xx – 成功(表明服务器成功地接受了客户端请求)
    3xx – 重定向(客户端浏览器必须采取更多操作来实现请求。例如,浏览器可能不得不请 求服务器上的不同的页面,或通过代理服务器重复该请求)
    4xx – 客户端错误(发送错误,客户端有问题。例如,客户端请求不存在的页面,客户端 未提供有效的身份证验证信息) 5xx – 服务器错误(服务器由于遇到错误而不能完成该请求)
    常见的返回码有:
     200 OK - [GET]:服务器成功返回用户请求的数据
     201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功 
    202 Aceepted - []:表示一个请求已经进入后台排队(异步任务)
     204 NO CONTENT - [DELETE]:用户删除数据成功
     400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行 新建或修改数据的操作  401 Unauthorized -[
    ] :表示用户没有权限(令牌、用户名、密码错误)
     403 Forbidden -[] :表示用户得到授权(与 401 错误相对),但是访问被禁止
     404 NOT FOUND -[
    ]:用户发出的请求针对得到是不存在的记录,服务器没有进行操作, 该操作是幂等的
     406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求 JSON 格式,但 是只有 XML 格式)
     500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是 否成功

    9、什么是 DNS?

    答:DNS 是域名系统 (Domain Name System),DNS 是用来做域名解析的,它会在你上网输入 网址后,把它转换成 IP,然后去访问对方服务器;没有它,你想上百度就要记住百度的 IP, 但有了 DNS 的处理,你只需要记住对应网站的域名,即网址就可以了。

    10、请问你们公司是如何做接口测试的?

    答: 接口测试实际跟一般测试不同就是测试用例的设计部分。 ①获取接口规范。
    ②设计接口测试功能用例(主要从用户角度出发看接口能否实现业务需求,用例设计就是黑 盒用例那一套)。
    ③各种入参验证(正常情况,异常情况包括输入参数个数不对,类型不对,可选/必选,还 有考虑参数有互斥或关联的情况)。
    ④接口返回值各种验证(符合接口文档需求)
    ⑤了解接口实现逻辑,实现逻辑覆盖(语句/条件/分支/判定/…)
    ⑥接口能并发执行吗、安全吗,性能满足要求吗?
    ⑦采用工具或者自写代码来验证。
    ⑧发现问题跟功能测试一样,该报 bug 报 bug,该跟踪状态的跟踪状态。

    11、怎么设计接口测试用例?

    答: 通常,设计接口测试用例需要考虑以下几个方面:
    ①是否满足前提条件 有些接口需要满足前提,才可成功获取数据。常见的,需要登录 Token 逆向用例:针对是否满足前置条件(假设为 n 个条件),设计 0~n 条用例
    ②是否携带默认值参数 正向用例:带默认值的参数都不填写、不传参,必填参数都填写正确且存在的“常规”值, 其他不填写,设计 1 条用例
    ③业务规则、功能需求 这里根据时间情况,结合接口参数说明,可能需要设计 N 条正向用例和逆向用例
    ④参数是否必填 逆向用例:针对每个必填参数,都设计 1 条参数值为空的逆向用例
    ⑤参数之间是否存在关联 有些参数彼此之间存在相互制约的关系
    ⑥参数数据类型限制 逆向用例:针对每个参数都设计 1 条参数值类型不符的逆向用例
    ⑦参数数据类型自身的数据范围值限制 正向用例:针对所有参数,设计 1 条每个参数的参数值在数据范围内为最大值的正向用例

    12、你做接口测试,测什么?

    答:
    可用性测试 根据约定的协议、方法、格式内容,传输数据到接口经处理后返回期望的结果:
     接口功能是否正确实现;
     返回值测试 - 返回值除了内容要正确,类型也要正确,保证调用方能够正确地解析;
     参数值边界值、等价类测试; 错误和异常处理测试
     输入异常值(空值、特殊字符、超过约定长度等),接口能正确处理,且按预期响应;
     输入错误的参数,接口能正确处理,并按预期响应;
     多输入、少输入参数,接口能正确处理,且按预期响应
     错误传输数据格式(如 json 格式写成 form 格式)测试; 安全性测试,主要指传输数据的安全性:
     敏感数据(如密码、秘钥)等是否加密传输;
     返回数据是否含有敏感数据,如用户密码、完整的用户银行账号信息等;
     接口是否对传入的数据做安全校验,如身份 ID 加 token 类似校验;
     接口是否防止恶意请求(如大量伪造请求接口致使服务器崩溃); 性能测试,如接口的响应时间、并发处理能力、压测处理情况:
     并发请求相同的接口(特别为 POST 请求),接口的处理情况(如插入了相同的记录导致 数据出错,引发系统故障); 测码学院
     接口响应时长在用户可忍受的范围内;  对于请求量大的接口做压测,确定最大的瓶颈点是否满足当前业务需要;

    13、平常用什么工具测接口的?

    答:常用 http 协议接口测试工具,如:postman、fiddler、jmeter;webService 接口用 SoapUI、 jmeter 等。

    14、没有接口文档,如果做接口测试?

    本题主要考情商,通俗来说就是忽悠能力,先唬住面试官了再说,进去了也是瞎测测,随时 做好背锅的准备,当然,你肯定不能回答面试官不测(心理 mmp,脸上笑嘻嘻),接下来就是 扯犊子时间
    答:用抓包工具把接口抓取处理,然后针对性进行测试;接口中字段信息不清楚的,找时间
    集中寻求开发解答。(常用抓包工具 Fiddler、Charles 等)

    15、在手工接口测试或者自动化接口测试的过程中,上下游接口有数据依赖如何处理

    ? 答:用一个全局变量来处理依赖的数据,比如登录后返回 token,其它接口都需要这个 token, 那就用全局变量来传 token 参数。

    16、依赖于第三方数据的接口如何进行测试?

    答:mock 接着面试官会问你,如果 mock 的,然后你就顺着坑继续挖,搭建 mock 服务,参考这篇 http://www.51ste.com/share/det-485.html

    17、接口测试中,依赖登录状态的接口如何测试?

    答:依赖登录状态的接口的本质上是在每次发送请求时需要带上 session 或者 cookie 才能 发送成功,在构建 POST 请求时添加必要的 session 或者 cookie

    18、如何模拟弱网做测试

    ? 答:Fiddler 和 charles 都可以模拟弱网测试,平常说的模拟丢包,也是模拟弱网测试。具
    体可以看《几种弱网模拟方法,总有一种适合你》

    19、你平常做接口测试的过程中发现过哪些 bug?

    面试官出这个题,主要是想知道你是不是真的做过接口测试,毕竟现在很多小伙伴简历经过 包装(不包装连面试机会都没有,没办法,为了生存,能理解)
    答:
    常规错误,接口没实现,没按约定返回结果,边界值处理出错等。 输入异常值(空值、特殊字符、超过约定长度等),接口抛错,没做封装处理; 输入错误的参数、多输入、少输入参数,
    接口可能出现的错误; 安全性问题,如明文传输、返回结果含有敏感信息,没对用户身份信息做校验,没做恶意请 求拦截等;
    性能问题,如接口并发插入多条相同操作,响应时间过长,接口压测出现瓶颈等; 测码学院

    20、当一个接口出现异常时候,你是如何分析异常的?

    答: 先抓包,用 fiddler(charles)工具抓包,或者浏览器上 F12 调试工具;APP 上的话,那就 用 Fiddler 做代理,通过手机设置代理去看请求和返回报文; 查看后端日志,如 Linux 系统通过 xhell 连上服务器,查看接口日志,查看是否有报错信息 (命令:tail -f 日志文件);

    21、如何分析一个 bug 是前端还是后端的?

    答: 平常提 bug 的时候,前端开发和后端开发总是扯皮,不承认是对方的 bug。 这种情况很容易判断,先抓包看请求报文,对着接口文档,看请求报文有没问题,有问题就 是前端发的数据不对; 请求报文没问题,那就看返回报文,返回的数据不对,那就是后端开发的问题咯。

    22、你们做接口测试自动化吗?

    答:现在针对大量应用,普遍推崇做接口测试自动化,维护成本低、收益高。常用的工具有 许多,如 Jmeter、Robot Framework、pytest 等。

    23、列出几个 JMeter 监听器?

    一些 JMeter 监听器是: 集合报告 汇总报告 查看结果树 用表格查看结果 图形结果 BeanShell Listener 摘要报告等

    24、在 python 中进行数据驱动测试

    在 unittest 中,没有自带的数据驱动,我们得借助 ddt 来实现,首先,我们得在 python 运行环境中安装 ddt,用下列命令安装 pip install ddt 另 外 一 个 测 试 框 架 pytest , 它 自 带 数 据 驱 动 实 现 , 是 通 过 @pytest.mark.parametrize(argnames,argvalues) 来实现参数化的。 也可以根据自己需求用 python 实现数据的读取和驱动。

    25、接口自动化中的关联怎么处理?

    把上一个请求返回的结果传入到下一个请求的参数中,将请求的结果反射到一个类属性(使 用 setattr()函数),下一个请求去调用这个类属性

    26、自动化测试怎么校验结果?

    断言 ,预期结果与实际结果对比
    数据库校验,根据测试场景来查询数据库里的数据和请求之前的数据进行比对 测码学院

    27、自动化使用的测试框架是什么?

    简述自动化框架的设计、维护
    测试框架:python+unittest+requests+ddt+openpyxl+pymysql+logging
    python:入门简单,语法简洁
    unittest :定义一个测试用例类,具体的方法来维护测试用例的生命周期,测试场景行为, 测试用例 前置场景,行为,期望结果,实际结果,断言方法,Setup teardown 方法
    requests:接口调用 ,支持 http 请求的库,API 简洁,提供不同的 http 请求方法,支持 session,cookies,
    ddt :数据驱动,ddt 类装饰器,data 测试方法装饰器 unpack 解包可迭代的数据类型
    普通用户,数据库,配置文件—(基础数据)
    openpyxl: 数据管理 excel 管理数据,使用 openpyxl 模块来进行 excel 数据的读和写 (excle,csv, json, yaml, txt 都可以管理测试数据)
    pymysql:数据库交互,数据校验
    eval,json:数据格式的转换 Eval 将 python 支持的格式转换成对应的格式
    logging:日志处理, 统一日志输出格式,渠道,级别,执行结果的记录,便于定位问题
    jenkins:持续集成
    2/框架设计思路:数据驱动+结构分层(可读性,可维护性,可扩展性)
    数据驱动:将维护数据与代码分离,接口调用行为一致,针对不同的参数组合驱动不同的测 试场景,减少代码冗余
    结构分层:数据层+用例层+逻辑层
    数据层:测试数据的支撑 data.xls
    用例层:用例的执行 test_register.py test_recharge.py
    逻辑层:公用的方法的封装与提取 doexcle.py do_mysql.py http_requests.py logger.py 等模块
    3/框架设计步骤:
    准备测试数据: EXCEL 表准备测试用例—excel 数据的读取—参数值的替换 测码学院
    发起请求:请求方法(get/post 方法进行封装—URL 的拼接(不同—参数转化为字典
    拿到请求的返回值:解析返回值 code,status,msg 信息
    断言
    好处:
    1、自动化测试用例和手工测试用例的完美结合,减少重复工作
    2、配置灵活,可以自主切换测试环境,执行测试用例
    3、常用功能进行封装,逻辑清晰,易于维护
    4、统一执行入口,管理测试用例集:
    run.py 模块通过模糊查找来选择需要执行的测试用例
    5、持续集成,定时构建,快速反馈

    28、具体的在这个项目中自动化怎么应用到实际的,您对自动化结果的分析

    完成所有的自动化测试框架的设计和实现后,进行接口测试,然后集成到
    jenkins,配置定时执行,生成 html 报表,查看测试通过率,查看接口的功能
    每次发版时,进行回归测试,新功能开发未提测前

    展开全文
  • 从底层到上层依次是单元测试、服务测试、UI测试,越接近接近底层,收益成本比越高,我这要说的就是服务测试,也叫做接口测试、API测试接口测试 接口测试测试系统组件间接口的一种测试接口测试主要用于...
  • 随着行业的发展,编程能力逐渐成为软件测试从业人员的一项基本能力。因此在笔试和面试中常常会有一定量的编码题,主要考察以下几点。 基本编码能力及思维逻辑 基本数据结构(顺序表、链表、队列、栈、二叉树) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 94,052
精华内容 37,620
关键字:

python接口自动化测试

python 订阅