api自动化之:python3实现fiddler爬虫转化为httprunner自动化case

在这里插入图片描述

需求背景

传统测试开发的接口自动化工程模型

一般掌握python的测试开发人员都喜欢使用python创建一套自动化工程。其中,大部分人应该都接触过一套架构模式:

语言:python(2/3)

库:requests,unittest,htmltestrunner

以requests实现http请求,unittest实现断言及报告,htmltestrunner实现html测试报告的生成。这是三大主要核心结构。当然还有比如用mvc框架集自动化执行和测试报告预览的平台,又或者是用邮件库实现的测试报告发送等各种形式。

为什么由传统代码工程改为工具平台

测试的入门门槛是比较低的,可能开发人员必须是精通某一门语言,多种技术。而测试就存在不懂任何语言,不懂任何技术的情况,并且即便是技术流,那也未必恰好都会使用python,可能有些人更喜欢java,或者是其它语言。还有就是每个人都有一定的发展过程,总会有他的技术薄弱的阶段。另外,一个企业专门组织测试开发团队是比较消耗成本的,而自动化开发的工作放在个别人的手上就很难实现同步。所以开发测试平台是一种人人都能参与自动化开发的方式。

我们自动化平台的结构

我们是基于httprunner框架进行本地化改造实现的平台。但是核心功能没有做太多变化,只是做了很多加法。

httpruuner的实现是使用python3的django框架完成的,有web交互页面,mysql数据库。其中,requests和unittest还是他的主要核心。自动化测试用例的实现,要求测试人员掌握http协议,把请求的必要信息填入用例内,加上必要的响应断言,只要做好数据回收,保证用例可以反复执行就好。其中有些需要计算,遍历,筛选,随机等无法写死的参数,则必须使用python函数进行实现,在用例中调用函数即可。所以测试开发的工作在这个时候就是负责写这些工具化函数。

演变1:swagger爬虫

这一部分的实现我以后有机会会分享出来。swagger接口文档是放在源码上的框架,我通过爬取接口文档的api,把它转化成自动化平台用例的数据格式,插入到mysql中,就实现了代替手工去创建case的方式。测试人员只需要把必要的参数维护进去就够了,这样也能避免测试人员手工创建case的时候经常手误犯错。

演变2:fiddler爬虫

实现第一步之后,测试人员需要通过手工操作,根据fiddler的抓包结果去提取数据维护进swagger抓下来的无数据用例内。那么显然现在的主要工作就是找到在fiddler里想要抓的接口,如果是webform或query这种表单,就需要一个字段一个字段的复制,还是有些麻烦的。所以心生一计----对fiddler进行爬虫。

实现思路

fiddler是应用于windows平台一款http协议抓包工具。作为一个中间代理,可以抓到手机或者电脑上发出的http请求,从而进行分析。如果看到这里不知道fiddler是做什么用的,建议去网上搜索一下它的使用方式,这里就不做关于它的分享了。比如我打开fiddler,在要实现自动化的业务上进行一番操作,同时注意抓包结果,你至少要知道哪些是你需要的。这个时候可以删除不需要实现自动化的,重复的接口,只保留想要实现自动化的抓包记录。全选后,右键-sava-selected session-as text.也就是把抓包的结果储存到本地的一个txt文档里。
image.png

(为了保护我司域名,用张表情遮挡一下host)

保存下来之后见下图:

image.png

大概看一下:

1、请求方法

2、请求头内的:授权口令

3、入参

4、响应

这是几个必要参数。响应通常我们校验code是不是200就可以了。所以对于码农来说,就是把这个txt文件想要的东西爬出来做好归类,再以测试平台内数据存储需要的格式塞到库里就OK了。

上菜

def analysisFiddler(headers):
    f = open(r"D:\AutoBugrate\AuToBugrate\1616_Full.txt",encoding="utf-8").read()
    reqList = f.split("------------------------------------------------------------------")
    newReqList = []

    for i in reqList:
        a = i.split("\n")
        while "" in (a):
            a.remove("")
        if a != []:
            newReqList.append(a)
    nameList = []
    fullUrlList = []
    methodList = []
    for i in newReqList:
        host = i[1].split(": ")[1]
        nameList.append(i[0].split(" ")[1].split(host)[1].replace("/","_"))
        fullUrlList.append(i[0].split(" ")[1])
        methodList.append(i[0].split(" ")[0])
    # print(nameList)
    # print(fullUrlList)

    publicBaseReqList = [{'test':
               {'skipIf': {},
                 'request': {'url': url,
                             'times': '1',
                             'sleep': '0',
                             'method': method,
                             'headers': headers},
                 'rollback': {},
                 'name': name,
                 'validate': [{'comparator': 'equals',
                               'check': 'content.code',
                               'expected': 200}]}}
                for url,method,name in zip(fullUrlList,methodList,nameList)] #定义一个通用的request用于sql

    # print(publicBaseReqList)

    for i,l in zip(newReqList,publicBaseReqList):
        i.pop()
        for j in i:
            for k in (j.split(" ")):
                if "{" in k:
                    l['test']['request']['json'] = eval(k)


    # print(publicBaseReqList)


    create_time = update_time = dayTime_get()
    caseType = '1' #1表示用例 2表示配置
    belong_project = '外拓项目'
    include = "[{'config': ['2980', '外拓配置-ST']}]"
    author='julian'
    belong_module_id = '156'

    conn = pymysql.connect(
    host='192.168.x.xx',
    port=3306,
    user='root',
    password='xxxxxx',
    db='autobots',
    cursorclass=pymysql.cursors.DictCursor,
    charset='utf8'
    )
    cur = conn.cursor()

    for name,request in zip(nameList,publicBaseReqList):
        # if (not bool(re.search('[a-zA-Z]',name))) and (name not in popNameList):#v1.1增加
        insertCaseSql = '''INSERT INTO `autobots`.`testcaseinfo` (
                        `id`,`create_time`,`update_time`,
                        `type`,`name`,`belong_project`,
                        `include`,`author`,`request`,`belong_module_id`)
                        VALUES(NULL,"%s","%s","%s","%s","%s","%s","%s","%s","%s")'''%(
            create_time,update_time,caseType,name,belong_project,include,author,request,belong_module_id)
        print(insertCaseSql)
        print('-'*200)

        cur.execute(insertCaseSql)
        conn.commit()
        time.sleep(1)

    cur.close()
    conn.close()

analysisFiddler(headers={'Authorization': 'Bearer $Authorization'})

大概介绍一下代码思路:

1、首先读取fiddler的文档路径

2、文档内一一排减号作为两次不同接口请求的分割线,所以我们使用它先做一次粗分割

3、然后再利用换行符做进一步的分割,并去掉空行

4、先提取每个请求的第一行,先抽取出host,再以host为分割标记,截取url,把url中的路径标记"/“替换成”-",因为在平台内,用例名字里包含正斜杠会被解析成路径,从而报用例找不到。替换完后,作为用例名字,存好放在列表内。同理,把url提炼出来,把请求方法也提炼出来。

5、下一步publicBaseReqList这个字典,就是测试平台的数据库内存储的测试用例的数据结构。skipif是跳过的条件,这里空着即可。request里的内容是主要区别,包含url,重试次数,睡眠时间,请求方法,请求头。rollback是回滚条件,也空着。name就是用例名称,validate里面的内容就是断言。其中我把请求头放在形参内,因为仅用到一个身份口令,这一批接口是一致的。后面就是做一次for循环,使用抓出来的url,method,name三个列表,把数据分别组装进去。每一个case都有一套数据结构。

6、有了基础的请求结构,还缺最主要的,body。由于我抓的这批接口都是application/json格式,所以我直接用"{"去找到这个json串。为了避免最后面的响应串干扰,先把它pop掉。

7、再往下就是插库了,把数据库内必要的参数补全,比如创建人,创建时间,更新时间,用例所属的工程,模块,以及前提条件(include),这里就包含一些基础的登录操作,提供token等信息。

8、最后就是愉快的执行。

image.png

它确实与swagger爬出来的不一样,因为名字都是按照接口路径拼的,swagger的是有中文名字的,不过这个不重要。看看里面
请求:

image.png

断言:

image.png

总体执行一下:

image.png

全部通过。

但是不要高兴的太早,因为我知道我抓的这批接口都只是查询类的。如果有一些增删改之类的,应该需要做一些微调,局部参数化。但是这已经很节省时间了对不对,因为脚本不是只使用一次的。后续还会做进一步的优化,让它适应各种各样的类型。

比如请求头更丰富多变,用什么样的方法过滤form,query的请求格式,都需要兼容。

不过,掌握http协议,掌握python爬虫和正则,自然心中有码,逢山开路遇水搭桥呗。

最后: 你可以在公众号:伤心的辣条 ! 自行获取一份216页软件测试工程师面试宝典文档资料【免费的】要你就来。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

学习技术不要孤军奋战,最好是能抱团取暖,相互成就一起成长,群众效应的效果是非常强大的,大家一起学习,一起打卡,会更有学习动力,也更能坚持下去。你可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)

喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!


好文推荐

转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!

面试经:一线城市搬砖!又面软件测试岗,5000就知足了…

面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…

什么样的人适合从事软件测试工作?

那个准点下班的人,比我先升职了…

测试岗反复跳槽,跳着跳着就跳没了…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值