HttpRunner快速入门

2020-07-07 11:18:52 浏览数 (1)

安装

代码语言:javascript复制
$ pip install httprunner==2.3.0

搭建项目

代码语言:javascript复制
$ hrun --startproject demo
代码语言:javascript复制
Start to create new project: demo
CWD: /Users/zhongxin/PycharmProjects/learn_httprunner

created folder: demo
created folder: demo/api
created folder: demo/testcases
created folder: demo/testsuites
created folder: demo/reports
created file: demo/api/demo_api.yml
created file: demo/testcases/demo_testcase.yml
created file: demo/testsuites/demo_testsuite.yml
created file: demo/debugtalk.py
created file: demo/.env
created file: demo/.gitignore

项目结构

  • demo/api

最小单元,单个接口的操作

  • demo/testcases

一个测试点,多个接口依次调用

  • demo/testsuites

测试套,执行多个测试点

  • demo/reports

测试报告存放路径

  • demo/.env

环境配置文件

  • demo/debugtalk.py

使用python代码进行一些自定义操作

  • demo/.gitignore

git 版本管理提交时忽略的文件或文件夹

项目结构

单个接口实例

先写一个简单的接口

代码语言:javascript复制
import json
from flask import Flask, request, jsonify

app = Flask(__name__)

right_u_p = {
    "username": "测试游记",
    "password": "123456"
}


@app.route('/login', methods=['POST'])
def login():
    data = json.loads(request.data.decode())
    if data.get('username') == right_u_p['username'] and data.get('password') == right_u_p['password']:
        return jsonify({"Data": "账号密码正确"}), 200
    else:
        return jsonify({"Data": "账号密码错误"}), 401


if __name__ == '__main__':
    app.run()

demo/api中编写第一个登陆的接口测试login.yml

代码语言:javascript复制
name: 登陆接口
variables:
    var1: value1
    var2: value2
request:
    url: http://127.0.0.1:5000/login
    method: POST
    headers:
        Content-Type: "application/json"
    json:
        username: "测试游记"
        password: "123456"
validate:
    - eq: ["status_code", 200]

运行

代码语言:javascript复制
$ hrun /Users/zhongxin/PycharmProjects/learn_httprunner/demo/api/login.yml

单个接口

运行报告

运行报告

运行详情

查看详情

使用环境变量

修改demo/.env

代码语言:javascript复制
USERNAME=测试游记
PASSWORD=123456
代码语言:javascript复制
name: 登陆接口
variables:
    var1: value1
    var2: value2
request:
    url: http://127.0.0.1:5000/login
    method: POST
    headers:
        Content-Type: "application/json"
    json:
        username: ${ENV(USERNAME)}
        password: ${ENV(PASSWORD)}
validate:
    - eq: ["status_code", 200]

定义全局变量

代码语言:javascript复制
name: 登陆接口
variables:
    uname: "测试游记"
    pwd: "123456"
request:
    url: http://127.0.0.1:5000/login
    method: POST
    headers:
        Content-Type: "application/json"
    json:
        username: $uname
        password: $pwd
validate:
    - eq: ["status_code", 200]

定义方法

variables中定义

使用方法

使用$变量名

调用python函数

demo/debugtalk.py中编写获取随机user_agent的函数

代码语言:javascript复制
def get_user_agent():
    user_agent = [
        "Mozilla/5.0 ce",
        "Mozilla/5.0 shi",
        "Mozilla/5.0 you",
        "Mozilla/5.0 ji",
    ]
    return random.choice(user_agent)

login.yml中使用

代码语言:javascript复制
name: 登陆接口
variables:
    uname: "测试游记"
    pwd: "123456"
request:
    url: http://127.0.0.1:5000/login
    method: POST
    headers:
        Content-Type: "application/json"
        User-Agent: ${get_user_agent()}
    json:
        username: $uname
        password: $pwd
validate:
    - eq: ["status_code", 200]

base_url

提取url路径

代码语言:javascript复制
name: 登陆接口
variables:
    uname: "测试游记"
    pwd: "123456"
base_url: http://127.0.0.1:5000
request:
    url: /login
    method: POST
    headers:
        Content-Type: "application/json"
        User-Agent: ${get_user_agent()}
    json:
        username: $uname
        password: $pwd
validate:
    - eq: ["status_code", 200]

validate

查看httprunner的源码:./site-packages/httprunner/validator.py

get_uniform_comparator可以看出它支持的断言以及其简写方式

代码语言:javascript复制
def get_uniform_comparator(comparator):
    """ convert comparator alias to uniform name
    """
    if comparator in ["eq", "equals", "==", "is"]:
        return "equals"
    elif comparator in ["lt", "less_than"]:
        return "less_than"
    elif comparator in ["le", "less_than_or_equals"]:
        return "less_than_or_equals"
    elif comparator in ["gt", "greater_than"]:
        return "greater_than"
    elif comparator in ["ge", "greater_than_or_equals"]:
        return "greater_than_or_equals"
    elif comparator in ["ne", "not_equals"]:
        return "not_equals"
    elif comparator in ["str_eq", "string_equals"]:
        return "string_equals"
    elif comparator in ["len_eq", "length_equals", "count_eq"]:
        return "length_equals"
    elif comparator in ["len_gt", "count_gt", "length_greater_than", "count_greater_than"]:
        return "length_greater_than"
    elif comparator in ["len_ge", "count_ge", "length_greater_than_or_equals", 
        "count_greater_than_or_equals"]:
        return "length_greater_than_or_equals"
    elif comparator in ["len_lt", "count_lt", "length_less_than", "count_less_than"]:
        return "length_less_than"
    elif comparator in ["len_le", "count_le", "length_less_than_or_equals", 
        "count_less_than_or_equals"]:
        return "length_less_than_or_equals"
    else:
        return comparator

查看返回信息中的字段

代码语言:javascript复制
name: 登陆接口
variables:
    uname: "测试游记"
    pwd: "123456"
base_url: http://127.0.0.1:5000
request:
    url: /login
    method: POST
    headers:
        Content-Type: "application/json"
        User-Agent: ${get_user_agent()}
    json:
        username: $uname
        password: $pwd
validate:
    - eq: ["status_code", 200]
    - eq: ["content.Data", "账号密码正确"]

testcases

为了测试连续多个步骤

场景:登陆后获取项目信息

修改接口代码

代码语言:javascript复制
import json
from flask import Flask, request, jsonify

app = Flask(__name__)

right_u_p = {
    "username": "测试游记",
    "password": "123456"
}


@app.route('/login', methods=['POST'])
def login():
    data = json.loads(request.data.decode())
    if data.get('username') == right_u_p['username'] and data.get('password') == right_u_p['password']:
        return jsonify({"Data": "账号密码正确", "token": "123456"}), 200
    else:
        return jsonify({"Data": "账号密码错误"}), 401


@app.route('/projects')
def project():
    print(request.headers.get("Authorization"))
    if request.headers.get("Authorization") == '123456':
        return jsonify({"Data": []}), 200
    else:
        return jsonify({"Data": []}), 401


if __name__ == '__main__':
    app.run()

demo/api/get_project_list.yml

代码语言:javascript复制
name: 获取项目信息
variables:
    token: "xxxxx"
base_url: http://127.0.0.1:5000
request:
    url: /projects
    method: GET
    headers:
        Content-Type: "application/json"
        Authorization: $token
validate:
    - eq: ["status_code", 200]

demo/testcases/get_project.yml

可以直接使用已经编写好的接口yaml文件当作步骤

代码语言:javascript复制
config:
    name: "获取项目信息"
    variables:
        username: ${ENV(USERNAME)}
        password: ${ENV(PASSWORD)}
    base_url: "http://127.0.0.1:5000"

teststeps:
-
    name: 登陆
    api: api/login.yml
    extract:
        - token: content.token
-
    name: 获取项目列表信息
    api: api/get_project_list.yml

testsuites

单个接口demo/api/login.yml

代码语言:javascript复制
name: 登陆接口
variables:
    uname: "测试游记"
    pwd: "123456"
base_url: http://127.0.0.1:5000
request:
    url: /login
    method: POST
    headers:
        Content-Type: "application/json"
        User-Agent: ${get_user_agent()}
    json:
        username: $uname
        password: $pwd
validate:
    - eq: ["status_code", 200]
    - eq: ["content.Data", "账号密码正确"]

参数不固定的接口测试demo/testcases/login.yml

缺少参数:

  • title 标题
  • uname 账号
  • pwd 密码
代码语言:javascript复制
config:
    name: "登陆接口配置"
    base_url: "http://127.0.0.1:5000"

teststeps:
-
    name: $title
    api: api/login.yml
    validate:
        - eq: ["status_code", $status_code]
        - eq: ["content.Data", $content_data]

参数遍历的测试套demo/testsuites/login.yml

使用直接写入

代码语言:javascript复制
config:
  name: "接口套件"


testcases:
  - name: "登陆接口套件"
    testcase: testcases/login.yml
    parameters:
      - title-uname-pwd-status_code-content_data:
          - ["正常登陆","测试游记","123456",200,"账号密码正确"]
          - ["账号错误","测试游记1","",401,"账号密码错误"]
          - ["密码错误","测试游记","1234567",401,"账号密码错误"]
          - ["账号为空","","1234567",401,"账号密码错误"]
          - ["密码为空","测试游记","",401,"账号密码错误"]

测试报告

使用csv

新建demo/datas/account.csv

代码语言:javascript复制
title,uname,pwd,status_code,content_data
正常登陆,测试游记,123456,200,账号密码正确
账号错误,测试游记1,,401,账号密码错误
密码错误,测试游记,1234567,401,账号密码错误
账号为空,,1234567,401,账号密码错误
密码为空,测试游记,,401,账号密码错误
代码语言:javascript复制
config:
  name: "接口套件"


testcases:
  - name: "登陆接口套件"
    testcase: testcases/login.yml
    parameters:
      - title-uname-pwd-status_code-content_data: ${P(datas/account.csv)}

使用csv会出现str和int类型比较的问题,需要在demo/debugtalk.py编写代码解决

命令行执行

代码语言:javascript复制
from httprunner.api import HttpRunner

httpruner = HttpRunner()

httpruner.run(r'/Users/zhongxin/PycharmProjects/learn_httprunner/demo/testsuites/login.yml')
print(httpruner.summary)

0 人点赞