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__': , '__weakref__': , '__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']
                                          
                                          #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}
                                          

文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码