Httprunner框架学习1--基本使用

1.Httprunner简介

官网https://testerhome.com/opensource_projects/httprunner

HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份YAML/JSON脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。

  • 继承 Requests 的全部特性,轻松实现 HTTP(S) 的各种测试需求
  • 测试用例与代码分离,采用YAML/JSON的形式描述测试场景,保障测试用例具备可维护性
  • 测试用例支持分层机制,充分实现测试用例的复用
  • 测试用例支持参数化和数据驱动机制
  • 使用 skip 机制实现对测试用例的分组执行控制
  • 支持热加载机制,在文本测试用例中轻松实现复杂的动态计算逻辑
  • 基于 HAR 实现接口录制和用例生成功能(har2case
  • 结合 Locust 框架,无需额外的工作即可实现分布式性能测试
  • 执行方式采用 CLI 调用,可与 Jenkins 等持续集成工具完美结合
  • 测试结果统计报告简洁清晰,附带详尽统计信息和日志记录
  • 具有可扩展性,便于扩展实现 Web 平台化(HttpRunnerManager

2.环境搭建

pip install httprunner

3.基本使用介绍

httprunner主要是通过YAML或JSON形式描述各种测试用例的,当你有了YAML或JSON格式的测试用例后,只需执行

hrun xxx.yml,或hrun xxx.json,即可执行测试用例

所以学习httprunner主要是编写yml或json格式的测试用例

yml或json格式的用例有两种方法获取1.自己编写2.通过抓包,使用har2case工具转换获得

先来一个简单的录制获取用例的demo

1.准备api_server.py,这个是一个flask框架编写的接口文件,需要先安装flask框架,

import hashlib
import hmac
import json
import random
import string
from functools import wraps

from flask import Flask, make_response, request

SECRET_KEY = "DebugTalk"

app = Flask(__name__)

""" storage all users' data
data structure:
    users_dict = {
        'uid1': {
            'name': 'name1',
            'password': 'pwd1'
        },
        'uid2': {
            'name': 'name2',
            'password': 'pwd2'
        }
    }
"""
users_dict = {}

""" storage all token data
data structure:
    token_dict = {
        'device_sn1': 'token1',
        'device_sn2': 'token1'
    }
"""
token_dict = {}


def gen_random_string(str_len):
    """ generate random string with specified length
    """
    return ''.join(
        random.choice(string.ascii_letters + string.digits) for _ in range(str_len))

def get_sign(*args):
    content = ''.join(args).encode('ascii')
    sign_key = SECRET_KEY.encode('ascii')
    sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest()
    return sign

def gen_md5(*args):
    return hashlib.md5("".join(args).encode('utf-8')).hexdigest()


def validate_request(func):

    @wraps(func)
    def wrapper(*args, **kwargs):
        device_sn = request.headers.get('device_sn', "")
        token = request.headers.get('token', "")

        if not device_sn or not token:
            result = {
                'success': False,
                'msg': "device_sn or token is null."
            }
            response = make_response(json.dumps(result), 401)
            response.headers["Content-Type"] = "application/json"
            return response

        if token_dict.get(device_sn) != token:
            result = {
                'success': False,
                'msg': "Authorization failed!"
            }
            response = make_response(json.dumps(result), 403)
            response.headers["Content-Type"] = "application/json"
            return response

        return func(*args, **kwargs)

    return wrapper


@app.route('/')
def index():
    return "Hello World!"

@app.route('/api/get-token', methods=['POST'])
def get_token():
    device_sn = request.headers.get('device_sn', "")
    os_platform = request.headers.get('os_platform', "")
    app_version = request.headers.get('app_version', "")
    data = request.get_json()
    sign = data.get('sign', "")

    expected_sign = get_sign(device_sn, os_platform, app_version)

    if expected_sign != sign:
        result = {
            'success': False,
            'msg': "Authorization failed!"
        }
        response = make_response(json.dumps(result), 403)
    else:
        token = gen_random_string(16)
        token_dict[device_sn] = token

        result = {
            'success': True,
            'token': token
        }
        response = make_response(json.dumps(result))

    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/users')
@validate_request
def get_users():
    users_list = [user for uid, user in users_dict.items()]
    users = {
        'success': True,
        'count': len(users_list),
        'items': users_list
    }
    response = make_response(json.dumps(users))
    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/reset-all')
@validate_request
def clear_users():
    users_dict.clear()
    result = {
        'success': True
    }
    response = make_response(json.dumps(result))
    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/users/<int:uid>', methods=['POST'])
@validate_request
def create_user(uid):
    user = request.get_json()
    if uid not in users_dict:
        result = {
            'success': True,
            'msg': "user created successfully."
        }
        status_code = 201
        users_dict[uid] = user
    else:
        result = {
            'success': False,
            'msg': "user already existed."
        }
        status_code = 500

    response = make_response(json.dumps(result), status_code)
    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/users/<int:uid>')
@validate_request
def get_user(uid):
    user = users_dict.get(uid, {})
    if user:
        result = {
            'success': True,
            'data': user
        }
        status_code = 200
    else:
        result = {
            'success': False,
            'data': user
        }
        status_code = 404

    response = make_response(json.dumps(result), status_code)
    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/users/<int:uid>', methods=['PUT'])
@validate_request
def update_user(uid):
    user = users_dict.get(uid, {})
    if user:
        user = request.get_json()
        success = True
        status_code = 200
        users_dict[uid] = user
    else:
        success = False
        status_code = 404

    result = {
        'success': success,
        'data': user
    }
    response = make_response(json.dumps(result), status_code)
    response.headers["Content-Type"] = "application/json"
    return response

@app.route('/api/users/<int:uid>', methods=['DELETE'])
@validate_request
def delete_user(uid):
    user = users_dict.pop(uid, {})
    if user:
        success = True
        status_code = 200
    else:
        success = False
        status_code = 404

    result = {
        'success': success,
        'data': user
    }
    response = make_response(json.dumps(result), status_code)
    response.headers["Content-Type"] = "application/json"
    return response
if __name__ == '__main__':
    app.run()

直接运行后,访问http://127.0.0.1:5000/

使用fiddler抓包后,

selected Sessions,选择httpArchive v1.1,导出为test.har

2.使用har2case将har文件转换为yml或json格式

不加 -2y参数默认转换为json格式,加了后是yml格式

test.json

{
    "teststeps": [
        {
            "validate": [
                {
                    "eq": [
                        "status_code", 
                        200
                    ]
                }, 
                {
                    "eq": [
                        "headers.Content-Type", 
                        "text/html; charset=utf-8"
                    ]
                }
            ], 
            "request": {
                "url": "http://127.0.0.1:5000/", 
                "headers": {
                    "User-Agent": "Fiddler"
                }, 
                "method": "GET"
            }, 
            "name": "/"
        }
    ], 
    "config": {
        "variables": {}, 
        "name": "testcase description"
    }
}

test.yml

config:
    name: testcase description
    variables: {}
teststeps:
-   name: !!python/unicode '/'
    request:
        headers:
            !!python/unicode 'User-Agent': !!python/unicode 'Fiddler'
        method: !!python/unicode 'GET'
        url: !!python/unicode 'http://127.0.0.1:5000/'
    validate:
    -   eq:
        - status_code
        - 200
    -   eq:
        - headers.Content-Type
        - !!python/unicode 'text/html; charset=utf-8'

生成的就是测试用例了,然后使用命令进行运行,

可以查看生成的报告

 

发布了97 篇原创文章 · 获赞 10 · 访问量 1万+
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 1024 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览