HttpRunner3.x 详细学习笔记(二)

本文档介绍了HttpRunner在接口自动化测试中的参数化方法,包括从环境变量、YAML文件、debugtalk.py函数中提取和引用数据,以及使用CSV文件进行参数化。还涉及到了hook机制、签名计算、文件上传、数据库操作和接口测试后的数据库验证。此外,文档还阐述了如何处理注册用例的唯一性问题,如通过时间戳生成随机用户名,以及使用setup和teardown钩子函数进行请求预处理和后处理。
摘要由CSDN通过智能技术生成

第 3 章 辅助函数(debugtalk.py)

3.1 参数关联(extract)

如何将上个登录接口的返回token,传给下个接口当做请求参数?
参数关联场景:
1.登录返回token -> 2.下个接口头部传token
extract 提取变量
$token 引用变量
在这里插入图片描述
一般在提取变量后,需在 config 中 export 导出变量 导出变量的目的是,使他变成全局变量,方便后面步骤调用 (在一个 yml 用例 引用另外一个 yml 用例的时候用得到)
在这里插入图片描述

3.2 环境变量 .env

在自动化测试项目的根目录中,创建 .env 文件, 并将敏感数据信息放置到其中,存储采用 name=value 的格式 (数据库配置信息等)
如:
username=test
password=123456
base_url=http://49.235.92.12:8201

项目根目录新建 .env 保存测试数据
在这里插入图片描述
引用环境变量 ${ENV(key)}
在这里插入图片描述

3.3 Testcaes 引用 Testcase

用例1 登录 export导出提取的token,方面后面引用
在这里插入图片描述
引用testcase:yml case相对路径
被引用的testcase中需要提取下一个case要用到的参数
在这里插入图片描述

在这里插入图片描述

3.4 场景案例 – 参数化和数据驱动

参数化在 config 中使用 parameters 关键字
Httprunner 2.x是在 testsuite 中实现参数化
Httprunner 3.x是在 testcase 的 Config 中实现参数化

3.4.1 单个参数参数化

准备四组登录用的账号和密码账号为test1,test2,test3,test4,密码统一设置为123456。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4.2 多个参数一一对应 - 参数化在这里插入图片描述
3.4.3 笛卡尔积 组合参数

比如测试账号有四种[“test1”, “test2”, “test3”, “test4”],密码也有四种 [“123456”, “123456”, “123456”, “123456”] 用笛卡尔积组合的话,就是4*4=16种组合
没办法控制测试结果,一半用于测试结果是一样的测试场景

在这里插入图片描述
参数化

httprunner 参数化数据源指定支持三种方式:

  • 在 YAML/JSON 中直接指定参数列表: 该种方式最为简单易用,适合参数列表比较小的情况
  • 通过内置的 parameterize(可简写为P)函数引用 CSV 文件:该种方式需要 准备 CSV 数据文件,适合数据量比较大的情况
  • 调用 debugtalk.py 中自定义的函数生成参数列表:该种方式最为灵活,可通 过自定义 Python 函数实现任意场景的数据驱动机制,当需要动态生成参数列表 时也需要选择该种方式 本节讲解内置的 parameterize(可简写为P)函数引用 CSV 文件

3.5 参数化引用CSV文件

3.5.1 yml 文件引用CSV文件

data/user_password.csv 文件存测试数据 user, psw
在这里插入图片描述
yml 文件引用 data/user_password.csv 文件 ${P(data/xx.csv)} 引用测试数据文件,可以支持相对路径,以项目根目录(debugtalk.py)为节点
在这里插入图片描述

3.6 参数化引用 debugtalk 函数

在这里插入图片描述
登录参数化案例 debugtalk.py生成测试数据
在这里插入图片描述
testcase 里面 yml 文件引用函数 ${get_account(4)}
test1-test4 账号是提前注册好的
在这里插入图片描述

3.7 注册案例(随机变量)

需求:自动化需要多次反复运行注册用例
遇到问题:注册账号,同一个账号只能注册一次
解决思路:
1.注册账号加时间戳(随机变量)
2.连数据库先删掉此账号
1.注册账号加时间戳(随机变量):
Debugtalk.py写个函数,生成带时间戳的用户名
在这里插入图片描述
yml 引用函数${register_user()}
在这里插入图片描述

3.8 hook机制(setup和teardown)

HttpRunner3.x 是基于 python Pytest 框架,里面也有前置 和后置 的概念。
setup_hooks(函数名称不是固定的): 开始执行前触发 hook 函数,主要用于请求预处理(签名,加密)。
teardown_hooks: 结束执行后触发 hook 函数,主要用于返回预处理(解密)。

在debugtalk.py写2个简单函数
在这里插入图片描述
带上-s查看详细日志 hrun testcase/part3/login_hook.yml -s
在这里插入图片描述
request是请求对象,req_json是对应的
在这里插入图片描述
在这里插入图片描述

3.9 sign签名案例

在请求的body中加一个sign参数,是一个加密的字符串
在这里插入图片描述

# debugtalk.py
import hashlib


def sign_body(body, apikey="12345678"):
    '''请求body sign签名'''
    # 列表生成式,生成key=value格式
    a = ["".join(i) for i in body.items() if i[1] and i[0] != "sign"]
    # print(a)
    # 参数名ASCII码从小到大排序
    strA = "".join(sorted(a))
    # print(strA)

    # 在strA后面拼接上apiKey得到striSignTemp字符串
    striSignTemp = strA+apikey

    # 将strSignTemp字符串转换为小写字符串后进行MD5运算

    # MD5加密
    def jiamimd5(src):
        m = hashlib.md5()
        m.update(src.encode('UTF-8'))
        return m.hexdigest()
    sign = jiamimd5(striSignTemp.lower())
    # print(sign)
    return sign


def login_sign(request):
    body = request.get("req_json")
    print("签名前body:", body)
    sign = sign_body(body=body, apikey="12345678")
    print("sign:", sign)
    request["req_json"]["sign"] = sign
    print("request:", request)
config:
    name: 用例描述-登录用例
    base_url: http://49.235.92.12:8201
    variables:
        user: test
        psw: "123456"
    export:
    - token

teststeps:
-
    name: step-登录
    setup_hooks:#$request 内置变量
    - ${login_sign($request)}
    request:
        url: /api/v3/login
        method: POST
        json:
            username: $user
            password: $psw
            sign: xxxxx
    extract:
        token: body.token
    validate:
        - eq: [status_code, 200]
        - eq: [body.msg, login success!]
        - eq: [body.code, 0]
        - eq: [body.username, $user]
        - len_eq: [body.token, 40]

3.10文件上传

upload关键字上传文件
图片放data目录,相对路径引用图片地址
在这里插入图片描述

3.11 连接数据库增删改查

pip install PyMysql==0.9.3

在这里插入图片描述
需求:接口操作完成后,校验数据库校验数据库,需用python连接数据库增删改查
项目下新建utils目录,添加连接数据库公共操作

import pymysql
'''
pip install PyMySQL==0.9.3
'''

# 配置数据库相关信息
dbinfo = {
    "host": "xx.xxx.xx.xx",
    "user": "root",
    "password": "123456",
    "port": 3309}


class DbConnect(object):
    def __init__(self, db_cof, database=""):
        # 打开数据库连接
        self.db = pymysql.connect(database=database,
                                  cursorclass=pymysql.cursors.DictCursor,
                                  **db_cof)

        # 使用cursor()方法获取操作游标
        self.cursor = self.db.cursor()

    def select(self, sql):
        # SQL 查询语句
        # sql = "SELECT * FROM EMPLOYEE \
        #        WHERE INCOME > %s" % (1000)
        self.cursor.execute(sql)
        results = self.cursor.fetchall()
        return results

    def execute(self, sql):
        # SQL 删除、提交、修改语句
        # sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
        try:
           self.cursor.execute(sql)  # 执行SQL语句
           self.db.commit()  # 提交修改
        except:
           # 发生错误时回滚
           self.db.rollback()

    def close(self):
        # 关闭连接
        self.db.close()

if __name__ == '__main__':
   
    db = DbConnect(dbinfo, database="apps")
    # 查询
    sql1 = 'SELECT * from apiapp_goods WHERE id = 1;'
    res1 = db.select(sql1)
    print(res1)

    # 执行
    sql2 = 'UPDATE apiapp_goods SET goodsname="xx" WHERE id=1;'
    db.execute(sql2)
    db.close()



修改商品信息接口,修改商品状态后
校验数据库对应的goodsstatus状态有没更新成功

①先调用接口修改商品

config:
    name: 用例描述-修改商品用例
    base_url: http://49.235.92.12:8201
    variables:
        sp_id: 1
        goodsname: yy
        goodscode: "sp_100861117"
        merchantid: "10001"
        merchantname: "hh"
        goodsprice: 99.9
        stock: 100
        goodsgroupid: 0
        goodsstatus: 1
        price: 21.0

teststeps:
-
    name: 修改商品
    request:
        url: /api/v1/goods/$sp_id
        method: PUT
        json:
            goodsname: $goodsname
            goodscode: $goodscode
            merchantid: $merchantid
            merchantname: $merchantname
            goodsprice: $goodsprice
            stock: $stock
            goodsgroupid: $goodsgroupid
            goodsstatus: $goodsstatus
            price: $price
    validate:
        - eq: [status_code, 200]
        - eq: [body.code, 0]
        - eq: [body.msg, success!]
        - eq: [body.data.goodsstatus, '${get_db_goods($sp_id, goodsstatus)}']  #引用函数  

②在debugtalk.py根据商品id查询商品对应字段key

def get_db_goods(sp_id=1, key="goodsstatus"):
    db = DbConnect(dbinfo, database="apps")
    sql1 = 'SELECT * from apiapp_goods WHERE id = %s;' % sp_id
    res1 = db.select(sql1)
    print(res1)
    if len(res1) == 0:
        result = ''
    else:
        result = res1[0][key]
    return result
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值