test-express

test-express

接口自动化测试框架。采用 python3,基于 httprunner 开发。

特性

  • 继承 Requests 的全部特性,轻松实现 HTTP(S) 的各种测试需求
  • 测试用例与代码分离,采用 YAML(推荐)/JSON 的形式描述测试场景,保障测试用例具备可维护性
  • 测试用例支持分层机制,充分实现测试用例的复用
  • 测试用例支持参数化和数据驱动机制
  • 支持热加载机制,在文本测试用例中轻松实现复杂的动态计算逻辑
  • 测试结果统计报告简洁清晰,附带详尽统计信息和日志记录

安装

使用前,请先安装相关依赖库

pip3 install -r [项目根目录]/requirments.txt

安装检验

运行如下命令,若正常显示版本号,则说明 HttpRunner 安装成功。

$ hrun -V
>>> 2.5.7

约定

工作空间/项目 结构

推荐结构

- api # 接口描述文件
  - login_api.yml
  - get_nodes_api.yml
- testcases # 用例描述文件
  - get_nodes.yml
- testsuites # 套件描述文件
- debugtalk.py # 用于存放自定义函数
- .env # 用于配置环境变量
- data # 用于存放用例数据
  - account.csv
- reports # 存储 html 测试报告

使用概述

使用步骤

  1. 根据接口和测试目的编写用例描述文件(推荐yaml), like "get_nodes.yml"
  2. 执行 yaml 文件
hrun /path/to/get_nodes.yml
  1. 拿到测试报告

每次运行完后,在当前目录的 reports 目录下找到最新的 html 报告

  1. done.

如何编写用例描述文件是重点

概念

开始编写用例描述文件之前,有必要对相关概念作简要说明。

  • 测试步骤
  • 测试用例
  • 测试套件

测试步骤(teststep)

对于接口测试来说,每一个测试步骤就对应一个 API 的请求描述。

have a look

login_api.yml,登录接口

name: login
base_url: ${ENV(BASE_URL)}
variables:
    expected_status_code: 200
    content_code: 0
    username: "visitor"
    password: "v123456"

request:
    method: POST
    url: /user/login/
    headers:
        Content-Type: "application/json"
    json:
        username: $username
        password: $password
validate:
    - eq: [status_code, $expected_status_code]
    - eq: [headers.Content-Type, application/json]
    - eq: [content.code, $content_code]
#    - len_eq: [content.token, 5]
    - contains: [content.data, "token"]
extract:
    token: content.data.token

测试步骤关键字说明

key required format description
name Yes string 测试步骤的名称,在测试报告中将作为测试步骤的名称
request Yes dict HTTP 请求的详细内容;可用参数详见 python-requests 官方文档
variables No list of dict 测试步骤中定义的变量,作用域为当前测试步骤
extract No list 从当前 HTTP 请求的响应结果中提取参数,并保存到参数变量中(例如token),后续测试用例可通过$token的形式进行引用
validate No list 测试用例中定义的结果校验项,作用域为当前测试用例,用于实现对当前测试用例运行结果的校验
setup_hooks No list 在 HTTP 请求发送前执行 hook 函数,主要用于准备工作
teardown_hooks No list 在 HTTP 请求发送后执行 hook 函数,主要用户测试后的清理工作

extract

支持多种提取方式

  • 响应结果为 JSON 结构,可采用.运算符的方式,例如headers.Content-Type、content.success;
  • 响应结果为 text/html 结构,可采用正则表达式的方式,例如blog-motto">(.*)</h2>

validate

断言/验证

"comparator_name": [check_item, expect_value]
short comparator description
eq equals 判断实际结果和期望结果是否相等
lt less_than 判断实际结果小于期望结果
le less_than_or_equals 判断实际结果小于等于期望结果
gt greater_than 判断实际结果大于期望结果
ge greater_than_or_equals 判断实际结果大于等于期望结果
ne not_equals 判断实际结果和期望结果不相等
str_eq string_equals 判断转字符串后对比 实际结果和期望结果是否相等
len_eq length_equals 判断字符串或list长度
len_gt length_greater_than 判断实际结果的长度大于和期望结果
len_ge length_greater_than_or_equals 实际结果的长度大于等于期望结果
len_lt length_less_than 实际结果的长度小于期望结果
len_le length_less_than_or_equals 实际结果的长度小于等于期望结果

hooks

  • setup_hooks 函数放置于 debugtalk.py 中,并且必须包含三个参数:
    • method: 请求方法,e.g. GET, POST, PUT
    • url: 请求 URL
    • kwargs: request 的参数字典
  • teardown_hooks 函数放置于 debugtalk.py 中,并且必须包含一个参数:
    • resp_obj: requests.Response 实例

request 关键字

key required format description
base_url No string 测试用例请求 URL 的公共 host,指定该参数后,test 中的 url 可以只描述 path 部分
headers No dict request 中 headers 的公共参数,作用域为整个用例
export No list 整个用例输出的参数列表,可输出的参数包括公共的 variable 和 extract 的参数; 在 log-level 为 debug 模式下,会在 terminal 中打印出参数内

测试用例(testcase)

引用来自 wiki 的定义:

测试用例(testcase)应该是为了测试某个特定的功能逻辑而精心设计的,并且至少包含如下几点:

  • 明确的测试目的(achieve a particular software testing objective)
  • 明确的输入(inputs)
  • 明确的运行环境(execution conditions)
  • 明确的测试步骤描述(testing procedure)
  • 明确的预期结果(expected results)

在本框架中,测试用例是测试步骤的 有序 集合。

get_nodes.yml,获取 node 列表的用例

config:
    name: "get nodes"
    variables:
        username: "visitor"
        password: "v123456"
    base_url: ${ENV(BASE_URL)}

teststeps:
    - name: 第一步,登录
      api: api/maseeper/login_api.yml
      variables:
          expected_status_code: 200
          content_code: 0
      validate:
          - eq: ["status_code", $expected_status_code]
          - eq: [content.code, $content_code]
      extract:
          - token: content.data.token

    - name: 第二步,获取 nodes
      api: api/maseeper/get_nodes_api.yml
      variables:
          token: $token
          username: $username
  • teststeps,测试步骤的有序集合
  • config,为文件内的全局配置项

config 关键字说明

key required format description
name Yes string 用例名称,作为报告中的标题
parameters No list of dict 用于实现数据化驱动
variables No list of dict 定义的全局变量,作用域为整个用例
request No dict request 的公共参数,常用参数包括 base_url 和 headers

变量空间作用域

  • 测试步骤的变量空间(context)会继承或覆盖 config 中定义的内容;
    • 若某变量在 config 中定义了,在某 test 中没有定义,则该 test 会继承该变量
    • 若某变量在 config 和某 test 中都定义了,则该 test 中使用自己定义的变量值
  • 各个测试步骤(test)的变量空间相互独立,互不影响;
  • 如需在多个测试步骤(test)中传递参数值,则需要使用 extract 关键字,并且只能从前往后传递

录制生成测试套件

  1. 安装 har2case;
# install
$ pip install har2case
# check
$ har2case -V
>>>0.2.1
  1. 将抓包工具拿到的数据包导出为 HAR 格式的文件,like: login.har。


    markdown-img-paste-20200421172254366.png
  2. 通过 har2case 将 har 文件 转为 测试用例文件。

$ har2case docs/data/demo-quickstart.har -2y
INFO:root:Start to generate testcase.
INFO:root:dump testcase to YAML format.
INFO:root:Generate YAML testcase successfully: docs/data/demo-quickstart.yml

测试套件(testsuite)

测试用例集 是 测试用例 的 无序 集合,集合中的测试用例应该都是相互独立,不存在先后依赖关系的。

config:
    name: "maseeper testsuite"
    variables:
        username: "visitor"
        password: "v123456
    base_url: ${ENV(BASE_URL)}

testcases:
    - name: "获取 nodes"
      testcase: testcases/maseeper/get_nodes.yml
      variables:
          device_sn: $device_sn

    - name: "获取 envs"
      testcase: testcases/maseeper/get_envs.yml
      variables:
          expected_status_code: 200
          content_code: 0
      parameters:
          expected_status_code: [200, 201]
          content_code: [0, 1, 2]
  • testcases,测试用例的无序集合

parameters

参数化场景

当前版本只支持 testsuite 层。

参数化后,parameters 中的变量将采用笛卡尔积组合形成参数列表,依次覆盖 variables 中的参数,驱动测试用例的运行。

组织结构

组织结构涉及三个基础概念:

  • 测试套件
  • 测试用例
  • 测试步骤
测试用例结构

三者的关系

  • 测试套件包含多个/一个测试用例(YAML/JSON)
  • 一个测试用例包含多个/一个测试步骤(STEP)
  • 测试步骤对应YMAL/JSON文件中的 teststeps 子项,包含单个接口的全部内容,包括发起请求,解析响应结果,校验结果。

环境变量

终端环境变量

set

使用环境变量之前,需要先在系统中设置环境变量名称和值,传统的方式为使用 export 命令(Windows系统中使用 set 命令)

$ export UserName=admin
$ echo $UserName
admin

get

在程序中就可以对系统中的环境变量进行读取。

$ python
>>> import os
>>> os.environ["UserName"]
'admin'

.env 环境变量

默认情况下,在自动化测试项目的根目录中,创建 .env 文件,并将敏感数据信息放置到其中,存储采用 name=value 的格式。

set

$ cat .env
UserName=admin
Password=123456
PROJECT_KEY=ABCDEFGH

get

在用例描述文件中 引用 .env文件中的变量。

${ENV(UserName)}

附录

httprunner 手册

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352