关键字 开发-16 用例间参数关联

发布时间 2024-01-10 11:45:16作者: dack_deng

前言

在第8篇文章中,我们使用了extract从接口返回的response中提取了返回的字段值,那么这节将分析,如何将提取的值传递给下一个接口进行参数传递,以达到接口间的参数关联。

1. export提取

extract 提取结果后,之前是module 模块变量级别,现在需要提升到运行用例的session会话全局级别,可以用request内置fixtures来实现。

    def run(self):
        # 1.先获取到config中的变量variables
        if not self.raw.get('config'):
            self.raw['config'] = {}
        base_url = self.raw.get('config').get('base_url', None)  # 获取config中base_url
        config_variables = self.raw.get('config').get('variables',{})
        log.info(f'获取到的config中的变量:{config_variables}')
        # export提取,config_exports变量定义,必须为list
        config_exports: list = self.raw.get('config').get('export', [])
        if not isinstance(config_exports, list):  # config中的export必须要为list类型
            config_exports = []
            log.info("export must be type of list")

......

        def execute_yaml_case(args):
          """执行yaml 中用例部分,根据这个函数动态生成其他测试用例函数"""
          log.info(f"执行的参数: {args}")
          # 更新fixtures的返回值,到容器中
          self.context.update(args)

          # 被谁调用
          call_function_name = inspect.getframeinfo(inspect.currentframe().f_back)[2]
          log.info(f'执行的内容: {case[call_function_name]}')

          # ----------- 通过 config 获取 export 变量 ------
          request_config = args.get('request').config
          if not hasattr(request_config, 'export'):
              request_config.export = {}
          self.context.update(request_config.export)
          case_exports = []  # 用例中需要导出的变量收集
          # 模块变量优先级高
          self.context.update(self.module_variable)
          # ----------- export end ---------

......

          for step in case[call_function_name]:
            step_context = self.context.copy()
            step_name = step.get('name')
            if step_name:
                log.info(f'用例执行:{step_name}')
                step_name = render_template_obj.rend_template_any(step_name, **step_context)
            render_template_obj.rend_template_any(step, **step_context)  # 用例每步之前先渲染变量,方便上个接口提取给下个接口

......

            elif item == 'export':
                if isinstance(value, list):
                    for _export in value:
                        if _export not in case_exports:
                            case_exports.append(_export)

                        if step_context.get(_export):
                            export_dict = {}
                            export_dict[_export] = step_context.get(_export)
                            self.context.update(export_dict)

                else:
                    log.error("export must be list type")

          #  ---------用例结束,更新 export 变量到全局 ------
          for export_key in config_exports:
              request_config.export[export_key] = self.context.get(export_key)
          for export_key in case_exports:
              request_config.export[export_key] = self.context.get(export_key)
          if request_config.export:
              log.info(f"export 导出全局变量:{request_config.export}")
          #  ---------更新export end ------

yml说明:test_ext5用例中,第一步是获取token参数,通过extract提取,然后通过export导出到用例全局中,下一步引用token的提取值。

# testcase/test_ext.yml
test_ext5:
  -
    name: 登录-获取到token
    skipif: 20 > 50
    api: api/login.yml
    extract:
      code1: $.code
      code2: body.code
      token: $.body.token
    validate:
      - eq: [$.code, 0]
      - eq: [status_code, 200]
    export:
      - token

  -
    name: 步骤1
    api: api/login.yml
    print: ${token}
  -
    name: 步骤2
    api: api/login.yml
    print: ${token}

test_ext6:
  name: 6666
  api: api/login.yml
  print: ${token}

运行。