fiddler+httprunner 零编码实现接口自动化DEMO

安装httprunner

pip install -i https://pypi.douban.com/simple httprunner

验证下安装好没

hrun -h

在pycharm创建一个工程,项目叫hrun_demo

hrun --startproject hrun_demo

可以看到生成的4个目录和一个py文件
api 生成测试用例后,自动把测试用例放在这里

debugtalk.py 框架用的,新项目代码如下

import time

def sleep(n_secs):
    time.sleep(n_secs)

reports 框架运行后生成的测试报告会存放在这

testcases 测试用例存放目录

testsuites 测试套件

datas 新建的目录,存放抓包工具(fiddler/charles/postman)导出的har文件

套路:

  1. 生成har文件:使用fiddler抓包工具,将接口保存下来:File-Export Sessions->Selected Sessions,保存格式选择:HTTPArchive1.2,

  2. 将har文件转换为yml或者json文件,然后放到testcases

    进入到目录D:\hrun_demo\datas
    然后生成yml文件login.yml:har2case login_info.har -2y,把login.yml拷贝到testcases目录执行

  3. 修改框架冗余代码, 主要是删除注释的那些不需要的断言和文件头的前四行,修改完最终是如下代码

    config:
        name: testcase description
        variables: {}
    teststeps:
    -   name: /usr/login
        request:
            data:
                null: '{"usercode":"xxxx","passwd":"xxxx","appDomain":"127.0.0.1"}'
            headers:
                AUTH_TYPE: '1'
                Content-Type: application/x-www-form-urlencoded;charset=UTF-8
                User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
                    (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
                __REQUEST_TYPE: AJAX_REQUEST
                app-domain: 127.0.0.1
            method: POST
            params:
                passwd: 3lcmYJSnaKCGcaFMTaYQ7xxa==
                usercode: k_test
            url: http://127.0.0.1/usr/login
        validate:
        -   eq:
            - status_code
            - 200
        -   eq:
            - content.code
            - '01'
  4. 到这里脚本就准备好了,这里日志级别使用debug,我们运行一下看看效果,日志是很清晰的

    D:\hrun_demo\testcases
    $ hrun login.yml --log-level debug
    INFO     HttpRunner version: 2.2.6
    INFO     Start to run testcase: testcase description
    /usr/login
    INFO     POST http://www.sit.xxx.com.cn/usr/login
    DEBUG    request kwargs(raw): {'data': {None: '{"usercode":"xxxx","passwd":"yyyy==","appDomain":"www.xxxx.com.cn"}'}, 'headers': {'AUTH_TYPE': '1', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', '__REQUEST_TYPE': 'AJAX_REQUEST', 'app-domain': 'www.xxxx.com.cn'}, 'params': {'passwd': 'yyyy==', 'usercode': 'xxxx'}, 'verify': True}
    DEBUG    processed request:
    > POST http://www.xxxx.com.cn/usr/login
    > kwargs: {'data': {None: '{"usercode":"xxxx","passwd":"yyyy==","appDomain":"www.xxxx.com.cn"}'}, 'headers': {'AUTH_TYPE': '1', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', '__REQUEST_TYPE': 'AJAX_REQUEST', 'app-domain': 'www.xxxx.com.cn'}, 'params': {'passwd': 'yyyy==', 'usercode': 'xxxx'}, 'verify': True, 'timeout': 120}
    DEBUG
    ================== request details ==================
    url              : 'http://www.xxxx.com.cn/usr/login?passwd=yyyy%3D%3D&usercode=xxxx'
    method           : 'POST'
    headers          : {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'AUTH_TYPE': '1', 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', '__REQUEST_TYPE': 'AJAX_REQUEST', 'app-domain': 'www.xxxx.com.cn', 'Content-Length': '143'}
    body             : 'None=%7B%22usercode%22%3A%22xxxx%22%2C%22passwd%22%3A%223lcmYJSnaKCGcaFMTaYQ7g%3D%3D%22%2C%22appDomain%22%3A%22www.xxxx.com.cn%22%7D'
    
    DEBUG
    ================== response details ==================
    ok               : True
    url              : 'http://www.xxxx.com.cn/usr/login?passwd=yyyy%3D%3D&usercode=xxxx'
    status_code      : 200
    reason           : ''
    cookies          : <RequestsCookieJar[Cookie(version=0, name='AUTH_TOKEN', value='aaa.bbb.ccc-AeeGXpPE9MVw59vII516U0c4207f54e20492dbfb988bcd898bb80', port=None, port_specified=False, domain='www.xxxx.com.cn', domain_specified=True, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1610241403, discard=False, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='USER_CODE', value='xxxx', port=None, port_specified=False, domain='www.xxxx.com.cn', domain_specified=True, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1610241403, discard=False, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='JSESSIONID', value='D8C25F6D9B805B820F41D86D5B7D1F39', port=None, port_specified=False, domain='www.xxxx.com.cn', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)]>
    encoding         : 'UTF-8'
    headers          : {'Server': 'nginx/1.14.0', 'Date': 'Fri, 11 Dec 2020 01:16:42 GMT', 'Content-Type': 'application/json;charset=UTF-8', 'Content-Length': '241', 'Connection': 'keep-alive', 'Set-Cookie': 'JSESSIONID=D8C25F6D9B805B820F41D86D5B7D1F39; Path=/; HttpOnly, rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Thu, 10-Dec-2020 01:16:42 GMT, AUTH_TOKEN=aaa.bbb.ccc-AeeGXpPE9MVw59vII516U0c4207f54e20492dbfb988bcd898bb80; Max-Age=2592000; Expires=Sun, 10-Jan-2021 01:16:42 GMT; Domain=www.xxxx.com.cn; Path=/; HttpOnly, USER_CODE=xxxx; Max-Age=2592000; Expires=Sun, 10-Jan-2021 01:16:42 GMT; Domain=www.xxxx.com.cn; Path=/; HttpOnly', 'Access-Control-Allow-Origin': '*', 'X-Kong-Upstream-Latency': '882', 'X-Kong-Proxy-Latency': '3', 'Via': 'kong/1.5.1'}
    content_type     : 'application/json;charset=UTF-8'
    json             : {'code': '01', 'msg': 'login finished', 'userCode': 'xxx', 'authToken': 'aaa.bbb.ccc-AeeGXpPE9MVw59vII516U0c4207f54e20492dbfb988bcd898bb80'}
    
    INFO     status_code: 200, response_time(ms): 1090.63 ms, response_length: 241 bytes
    
    DEBUG    start to validate.
    DEBUG    extract: status_code   => 200
    DEBUG
    validate: status_code equals 200(int)   ==> pass
    DEBUG    extract: content.code  => 01
    DEBUG
    validate: content.code equals 01(str)   ==> pass
    .
    
    ----------------------------------------------------------------------
    Ran 1 test in 1.106s
    
    OK
    DEBUG    No html report template specified, use default.
    INFO     Start to render Html report ...
    INFO     Generated Html report: D:\hrun_demo\testcases\reports\1607649402.html

    不指定--log-level,日志级别默认为INFO

    D:\hrun_demo\testcases
    $ hrun login.yml
    INFO     HttpRunner version: 2.2.6
    INFO     Start to run testcase: testcase description
    /usr/login
    INFO     POST http://www.xxxx.com.cn/usr/login
    INFO     status_code: 200, response_time(ms): 1070.2 ms, response_length: 241 bytes
    
    .
    
    ----------------------------------------------------------------------
    Ran 1 test in 1.074s
    
    OK
    INFO     Start to render Html report ...
    INFO     Generated Html report: D:\hrun_demo\testcases\reports\1607649509.html
  5. 测试报告的存放规则,因为我是在D:\hrun_demo\testcases目录执行的,httprunner会在当前目录生成reports目录存放测试报告;如果你是在datas目录执行用例,报告则会生成在D:\hrun_demo\reports目录

到这里httprunner的demo就演示完了,这个套路还是数据驱动级别的框架,值得注意的是这里的yml脚本用例是可以直接通过locusts来执行压测的,locust部署也很简单,感兴趣的可以试一下

locusts -f testcases/login_info.yml

posted @ 2022-04-05 19:07  我是一言  阅读(124)  评论(0编辑  收藏  举报