demo/api
最小单元,单个接口的操作
demo/testcases
一个测试点,多个接口依次调用
demo/testsuites
测试套,执行多个测试点
demo/reports
测试报告存放路径
demo/.env
环境配置文件
demo/debugtalk.py
使用python代码进行一些自定义操作
demo/.gitignore
git 版本管理提交时忽略的文件或文件夹
项目结构先写一个简单的接口
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
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]运行
$ hrun /Users/zhongxin/PycharmProjects/learn_httprunner/demo/api/login.yml 单个接口运行报告
运行报告运行详情
查看详情修改demo/.env
USERNAME=测试游记 PASSWORD=123456 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]在variables中定义
使用$变量名
在demo/debugtalk.py中编写获取随机user_agent的函数
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中使用
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]提取url路径
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]查看httprunner的源码:./site-packages/httprunner/validator.py
从get_uniform_comparator可以看出它支持的断言以及其简写方式
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查看返回信息中的字段
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", "账号密码正确"]为了测试连续多个步骤
场景:登陆后获取项目信息
修改接口代码
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
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文件当作步骤
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单个接口demo/api/login.yml
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 密码
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
新建demo/datas/account.csv
title,uname,pwd,status_code,content_data 正常登陆,测试游记,123456,200,账号密码正确 账号错误,测试游记1,,401,账号密码错误 密码错误,测试游记,1234567,401,账号密码错误 账号为空,,1234567,401,账号密码错误 密码为空,测试游记,,401,账号密码错误 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编写代码解决