python-自动化测试- 多接口动态参数设计

什么叫做多接口的动态参数处理?

测试数据都放在excel中管理,每个接口如果有提取的数据就直接放在excel里写好,到时候直接读取出来做响应的提取操作即可。

  • 电商项目: 购物车 token proId skuID等 需要执行多个接口 获取返回值;

  • 业务流: 前面过很多步骤 【中间步骤都是单独的一个接口的请求】

  • 以上情况 都不太适合用conftest夹具测试使用。因为前置很多 处理比较麻烦。

  • 参考postman的处理方法。

    • 先执行前置登录-- 正常接口测试
    • 执行之后,提取数据-- 存在环境变量— 共享的 后面每个接口都可以调用数据,变量
    • 后面接口调用 – {{变量}} === 这个是{{}}是一个占位符,用你从环境变量里取到值 替换掉这个位置的数据 【Jmeter - ${}】
  • 设计的思路:业务流: 登录-搜索-进入详情页-添加购物车-查询购物车-结算-提交订单

    • 先把业务流的接口用例都写出来,在excel表格里统一管理表格设计好之后,我们需要用代码来实现: 提取数据---->存储环境变量—> 查找占位符 —> 替换变量的一系列操作。我们一步一步完成。
      • 1、关联的接口 需要提取的数据也提取出来: 加一个提取响应字段在excel里,用jsonpath提取
      • 2、代码提取出来后,保存在环境变量里 == 类 动态属性
      • 3、其他接口要用的位置用占位符表示,后面用代码替换成为 -环境变量里存的值。
  • 第一步:提取出来需要的响应字段的值 - 用jsonpath
    思路如下:

    • 1、先从excel标题读取【提取响应结果数据】这列; – 读取出来是字符串
    • 2、转化为字典-- json.loads()反序列化
    • 3、分别渠道这个提取表达式里的 key 和value ,key是字段名,value是jsonpath表达式。 – 用for循环遍历
    • 4、从接口的响应结果里使用这个jsonpath表达式提取数据。
  • 第二步:将响应字段存储到环境变量中(键-值,可以有多组): 数据读取出来后,要存起来: 全局共享给所有用例可用。

    • 用类的动态属性存储提取是的数据。
    • 类和类的属性 存出 环境变量的变量名 和值。 == setattr getattr
  • 第四步:用占位符包裹要替换的变量,然后用环境变量里的数据替换占位符位置的变量名。

    • 难点:代码如何自动识别这些要替换的数据?–用占位符 ; 占位符包裹的变量名出来? — 正则表达式匹配
      如果能识别出来,我们后续其实就比较简单了:
      • 1、取出来占位符中的变量名: 读取头部和参数的时候,判断是否有替换的值。有就替换。
      • 2、从环境变量获取属性值-- 变量值
      • 3、将变量名替换为属性值,再去用于发送接口请求【头部也有,参数也有】
"""
思路如下:
1、先从excel标题读取【提取响应结果数据】这列; -- 读取出来是字符串
2、转化为字典-- json.loads()反序列化
3、分别渠道这个提取表达式里的 key 和value ,key是字段名,value是jsonpath表达式。 -- 用for循环遍历
4、从接口的响应结果里使用这个jsonpath表达式提取数据。
"""
# 从excel里读取出来的 提取形影结果的表达式
import json
from jsonpath import jsonpath

# 这个类就是为了存储环境变量 实现环境变量的共享的
class EnviData:
    pass


response = {"access_token":"0efdce50-0e2f-4ed0-b4d1-944be5ab518a",
"token_type":"bearer","refresh_token":"4bfc3638-e7e4-4844-a83d-c0f8340bc146",
"expires_in":1295999,"pic":"http://mall.lemonban.com:8108/2023/09/b5a479b28d514aa59dfa55422b23a6f0.jpg",
"userId":"46189bfd628e4a738f639017f1d9225d","nickName":"lemon_auto","enabled":True}

extract_data = '{"access_token":"$..access_token","token_type":"$..token_type"}'

# 第一步: 反序列化 -字典
extract_data = json.loads(extract_data)
for k,v in extract_data.items():  # k 是access_token 变量名字,v是$..access_token
    # 使用jsonpath表达式 提取login响应结果里的值
    value = jsonpath(response,v)[0]  # 是access_token的具体值
    print(value)
    # 存起来到环境变量里去
    setattr(EnviData,k,value)
print(EnviData.__dict__)

运行结果如下:

0efdce50-0e2f-4ed0-b4d1-944be5ab518a
bearer
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'EnviData' objects>, '__weakref__': <attribute '__weakref__' of 'EnviData' objects>, '__doc__': None, 'access_token': '0efdce50-0e2f-4ed0-b4d1-944be5ab518a', 'token_type': 'bearer'}

正则表达式提取

  • 正则表达式是一组由字母和符号组成的特殊文本, 它可以用来从文本中找出满足你想要的格式的句子.
  • 主要针对字符串:
    • 1、判断字符串是否匹配我的规则
    • 2、提供正则表达式,从字符串提取出来匹配的内容。
  • 正则非常强大,开发特别是前端开发用的很多,语法非常多,没有必要都掌握,用到了再去查就可以。目前先学习我们要用的即可。

re相关的文章: https://www.cnblogs.com/Simple-Small/p/9150947.html

regular表达式学习手册: https://tool.oschina.net/uploads/apidocs/jquery/regexp.html(规则)

https://gitee.com/thinkyoung/learn_regex

在线的正则验证:https://c.runoob.com/front-end/854/

  • 正则的语法规则:

    • 1、匹配一个字符 (元字符)
      • \d 只匹配数字0-9
      • \w 匹配[0-9A-Za-z_] 数字字母下划线 支持中文
      • . 除了换行符(\n)以外的所有字符。
    • 2、正则的匹配次数
      • *匹配前一个字符,0次或者多次 ==任意次
      • +匹配前一个字符,1次或者多次
      • ?匹配前一个字符,0次或者1次
  • 我们用的做多就是万能表达式: 非贪婪匹配的 .*?

    • ? 非贪婪匹配模式:找到了## 两个后 不会再找了就匹配成功了;
      • 贪婪模式:尽可能去进行更多的匹配
      • 非贪婪模式:尽可能少的去进行匹配
  • Python的正则的库,内置库 re , 直接导入re 库,免安装

    • re模块函数 : findall(),search()
      • findall(正则表达式, 目标字符串) ,字符串从头到尾去匹配,只要符合要求就会拿出来
        • 多个符合的结果 存到列表里,返回一个列表。
        • 如果只想获取里面的变量名 不需要这个## 限定符,可以加个括号括起来: 加了括号,就是只提取括号里的内容,就是左右边界了。
      • search(正则表达式, 目标字符串)方法
        • 搜索查找,如果匹配的正则符合的话,返回Match类型的对象,不符合就返回None
        • Match类型的对象(search函数的返回值)的方法group() - 正则分组,可以返回的匹配的整体子串-整体占位
          符内容 #prodId#
        • search函数找到了第一个符合的之后,它就不会再继续往后去查找
"""
*
re模块函数 : findall(),search()
    * findall(正则表达式, 目标字符串) ,字符串从头到尾去匹配,只要符合要求就会拿出来
        * 多个符合的结果 存到列表里,返回一个列表。
        * 如果只想获取里面的变量名 不需要这个## 限定符,可以加个括号括起来: 加了括号,就是只提取括号里的内容,## 就是左右边界了。
    * search(正则表达式, 目标字符串)方法
        * 搜索查找,如果匹配的正则符合的话,返回Match类型的对象,不符合就返回None
        * Match类型的对象(search函数的返回值)的方法group() - 正则分组,可以返回的匹配的整体子串-整体占位符内容 #prodId#
        * search函数找到了第一个符合的之后,它就不会再继续往后去查找
            - 循环找: 先找到第一个,替换掉这个; 继续第二次,替换掉,第三次。。。。
            - 确定循环次数么?--不能确认循环次数的时候,用while。
            - while循环先进去,找不到占位符 -- 返回值None ,跳出循环。

思路:
1、环境变量里已经有了 属性名 --属性值
class EnviData:
    prodId = 7717
    skuId = 4563
2、先从类里获取属性值 -- getattr(EnviData,prodId) === prodId这个名字
3、先用正则找到这个字符串里的 占位符标记的字符串 ,replace(标记符,类属性值)

注意: 做的事情
- 第一个: 取到 #prodId#  == 被替换掉的子字符串
- 第二个: prodId  == 获取类属性变量。
"""

import re

str_data = '{"basketId": 0, "count": 1, "prodId": #prodId#, "shopId": 1, "skuId": #skuId#}'

# findall(正则表达式, 目标字符串) ,字符串从头到尾去匹配,只要符合要求就会拿出来
result = re.findall("#.*?#",str_data) # 结果是  #prodId#
print(result)
# 得到## 限定符里面的变量名:--加上括号就只会得到 #里面的值#
var_name = re.findall("#(.*?)#",str_data) #结果  prodId
print(var_name)

# search(正则表达式, 目标字符串)方法
result = re.search("#(.*?)#",str_data) # 结果是一个对象
print(result)
# 对象的group()方法 - 正则分组,可以返回的匹配的整体子串
value = result.group()  # 结果是  #prodId#
print(value)
var_name = result.group(1) # 第一个分组的值 结果是 prodId
print(var_name)


# 没有匹配到结果--None
result = re.search("#.*?!#",str_data) # 结果是一个对象
print(result)

运行结果如下:

['#prodId#', '#skuId#']
['prodId', 'skuId']
<re.Match object; span=(38, 46), match='#prodId#'>
#prodId#
prodId
None

循环正则提取

"""
*
re模块函数 : findall(),search()
    * findall(正则表达式, 目标字符串) ,字符串从头到尾去匹配,只要符合要求就会拿出来
        * 多个符合的结果 存到列表里,返回一个列表。
        * 如果只想获取里面的变量名 不需要这个## 限定符,可以加个括号括起来: 加了括号,就是只提取括号里的内容,## 就是左右边界了。
    * search(正则表达式, 目标字符串)方法
        * 搜索查找,如果匹配的正则符合的话,返回Match类型的对象,不符合就返回None
        * Match类型的对象(search函数的返回值)的方法group() - 正则分组,可以返回的匹配的整体子串-整体占位符内容 #prodId#
        * search函数找到了第一个符合的之后,它就不会再继续往后去查找
            - 循环找: 先找到第一个,替换掉这个; 继续第二次,替换掉,第三次。。。。
            - 确定循环次数么?--不能确认循环次数的时候,用while。
            - while循环先进去,找不到占位符 -- 返回值None ,跳出循环。

思路:
1、环境变量里已经有了 属性名 --属性值
class EnviData:
    prodId = 7717
    skuId = 4563
2、先从类里获取属性值 -- getattr(EnviData,prodId) === prodId这个名字
3、先用正则找到这个字符串里的 占位符标记的字符串 ,replace(标记符,类属性值)

注意: 做的事情
- 第一个: 取到 #prodId#  == 被替换掉的子字符串
- 第二个: prodId  == 获取类属性变量。
"""

import re

str_data = '{"basketId": 0, "count": 1, "prodId": #prodId#, "shopId": 1, "skuId": #skuId#}'
class EnviData:
    prodId = 7717
    skuId = 4563


while True:
    # search(正则表达式, 目标字符串)方法
    result = re.search("#(.*?)#",str_data) # 结果是一个对象
    if result is None:  # 如果没有占位符 就是None 跳出循环
        break
    mark = result.group()  # 结果是  #prodId# --要被替换的子字符串
    var_name = result.group(1) # 第一个分组的值 结果是 prodId
    # 从环境变量里获取变量名对应的属性值  prodId-- 属性值 7717,替换的数据
    var_value = getattr(EnviData,var_name)  # 结果 : 7717--int类型
    # 目标字符串的替换,赋值给一个变量
    # 注意:replace方法要求 两个参数都应该是字符串。
    str_data = str_data.replace(mark,str(var_value))
    print(str_data)

运行结果如下:

{"basketId": 0, "count": 1, "prodId": 7717, "shopId": 1, "skuId": #skuId#}
{"basketId": 0, "count": 1, "prodId": 7717, "shopId": 1, "skuId": 4563}

相关推荐

  1. python-自动化测试- 接口动态参数设计

    2024-03-27 17:32:01       22 阅读
  2. python+pytest接口自动化测试参数关联

    2024-03-27 17:32:01       42 阅读
  3. 高效接口测试Python自动化框架设计与实现

    2024-03-27 17:32:01       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-27 17:32:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 17:32:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 17:32:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 17:32:01       20 阅读

热门阅读

  1. yolo_tracking项目val代码解析

    2024-03-27 17:32:01       21 阅读
  2. Z字形变换

    2024-03-27 17:32:01       21 阅读
  3. Tomcat启动后快速闪退解决方法

    2024-03-27 17:32:01       23 阅读
  4. 指针的运算(萌新版)

    2024-03-27 17:32:01       16 阅读
  5. SpringMVC运行原理

    2024-03-27 17:32:01       18 阅读
  6. 函数模板案例---选择排序算法

    2024-03-27 17:32:01       18 阅读
  7. 记录一次AP重置经历

    2024-03-27 17:32:01       18 阅读