使用unittest框架接口测试中,yaml文件中有参数关联情景如何进行处理

使用unittest框架接口测试中,yaml文件中上一个接口的返回值在下一个接口的data中作为参数,yaml文件中如何进行编写

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在yaml文件中,可以使用以下格式来设置参数关联的情况:

test_case:
  - name: Test1
    url: http://www.example.com/api/login
    method: post
    data:
      username: testuser
      password: Test@123
      
  - name: Test2
    url: http://www.example.com/api/userinfo
    method: get
    headers:
      Authorization: $Token
    data:
      user_id: $user_info.user_id

在上面的示例中,Test2接口的headers中使用了$Token参数,该参数是从上一个接口(Test1)的返回值中获取的。而Test2接口的data中,使用了$user_info.user_id参数,该参数是从上一个接口(Test1)返回值中的user_id字段获取的。

在使用unittest框架进行接口测试时,需要在测试类中编写函数来读取yaml文件中的测试用例、执行测试,并进行断言。下面是一个示例代码:

import unittest
import requests
import yaml

class TestAPI(unittest.TestCase):
    
    def setUp(self):
        self.base_url = "http://www.example.com/api/"
        
    def test_api(self):
        with open("test_case.yaml", "r") as f:
            test_cases = yaml.safe_load(f)
        
        for test_case in test_cases:
            name = test_case["name"]
            url = self.base_url + test_case["url"]
            method = test_case["method"]
            headers = test_case.get("headers", {})
            data = test_case.get("data", {})
            
            # 处理参数关联
            for key, value in data.items():
                if isinstance(value, str) and value.startswith("$"):
                    previous_key = value[1:]
                    previous_resp = previous_resp if previous_resp else {}
                    data[key] = eval("previous_resp" + previous_key)
            
            # 发送请求
            resp = requests.request(method, url, headers=headers, json=data)
            resp_json = resp.json()
            previous_resp = resp_json  # 将当前接口的返回值存储到previous_resp中,供下一个接口使用

            # 断言
            self.assertEqual(resp.status_code, 200)
            
if __name__ == "__main__":
    unittest.main()

在上面的代码中,setUp函数用于设置测试用例的基础URL。test_api函数读取test_case.yaml文件中的测试用例,遍历每个接口,并对参数关联进行处理,然后发送请求并断言。previous_resp变量用于存储上一个接口的返回值,在下一个接口中使用。
如果我的回答解决了您的问题,请采纳!

请看以下示例:

test_case_1:
  url: http://example.com/api/login
  method: post
  headers:
    Content-Type: application/json
  data:
    username: testuser
    password: testpass
  asserts:
    - status_code: 200
    - response_json.code: 0
  extract:
    token: response_json.token

test_case_2:
  url: http://example.com/api/get_info
  method: get
  headers:
    Authorization: Bearer ${test_case_1.token}
  asserts:
      - status_code: 200
      - response_json.id: 123
      - response_json.name: testuser

在上面的示例中,test_case_1extract 的操作会将 response_json.token 存储在 test_case_1.token 中。下面的 test_case_2,可以使用 ${test_case_1.token} 的方式引用 test_case_1 中存储的值,作为其请求头中 Authorization 字段的值。如果你需要在下一个接口中使用其他的值作为参数,也可以使用类似 test_case_1.token 的方式在不同的测试用例之间传递数据。

在使用unittest框架进行接口测试时,如果yaml文件中有动态参数关联的情况,可以使用python中的字符串模板来进行处理。您可以在yaml文件中定义一个动态参数,然后使用字符串模板的方式将该参数与其他参数进行关联。例如:

testcase1:
  url: "/api/user/login"
  method: "POST"
  headers:
    Content-Type: "application/json"
  body:
    username: "user1"
    password: "password1"
  expected:
    code: 200
    message: "login success"
  dynamic_params:
    token: "$response.body.token"


在上面的yaml文件中,我们定义了一个动态参数 token,并使用字符串模板的方式将其与响应body中的token字段进行关联。在测试用例中,我们可以通过解析yaml文件,获取到该动态参数的值,然后在后续的测试用例中使用。例如:


import unittest
import yaml
import requests

class TestApi(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        with open("test.yaml", "r") as f:
            cls.test_data = yaml.safe_load(f)

    def test_login(self):
        url = self.test_data["testcase1"]["url"]
        method = self.test_data["testcase1"]["method"]
        headers = self.test_data["testcase1"]["headers"]
        body = self.test_data["testcase1"]["body"]

        response = requests.request(method, url, headers=headers, json=body)

        self.assertEqual(response.status_code, self.test_data["testcase1"]["expected"]["code"])
        self.assertEqual(response.json()["message"], self.test_data["testcase1"]["expected"]["message"])

        # 获取动态参数token的值,并保存到类属性中
        self.__class__.token = response.json()["body"]["token"]

    def test_query_user(self):
        url = self.test_data["testcase2"]["url"]
        method = self.test_data["testcase2"]["method"]
        headers = self.test_data["testcase2"]["headers"]
        # 使用字符串模板的方式,将动态参数token与url进行关联
        url = url.format(token=self.__class__.token)

        response = requests.request(method, url, headers=headers)

        self.assertEqual(response.status_code, self.test_data["testcase2"]["expected"]["code"])
        self.assertEqual(response.json()["message"], self.test_data["testcase2"]["expected"]["message"])

在上面的示例中,我们使用 test_login 测试用例中获取了动态参数token的值,并将其保存到了类属性中。然后,在后续的测试用例 test_query_user 中,我们可以使用字符串模板的方式,将该参数与请求url进行关联。这样就能够实现动态参数关联的功能了。
答案出自 https://www.wodianping.com/

  • 这篇博客: 自动化测试——unittest框架中的 (4) 、yaml文件驱动 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • -
      username: admin9
      password: 123456
    -
      username: normal
      password: 789456
    
    • 对应的json文件
    [
      {
        "username": "admin9",
        "password": 123456
      },
      {
        "username": "normal",
        "password": 7894
      }
    ]
    

    写法:

    """
    使用yaml数据驱动
    """
    
    import unittest
    from time import sleep
    
    from selenium import webdriver
    from ddt import ddt, data, unpack, file_data
    
    
    @ddt
    class YamlTest(unittest.TestCase):
        def setUp(self) -> None:
            self.driver = webdriver.Chrome()
            self.driver.get('file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8CA.html')
            self.driver.maximize_window()
    
        def tearDown(self) -> None:
            driver = self.driver
            sleep(3)
            driver.quit()
    
        # file_data 传入多个参数的时候,@unpack 的解包不起作用
        @unittest.skip
        @file_data('../user.yaml')
        @unpack
        def test_yaml01(self, username, password):
            driver = self.driver
            driver.find_element_by_id('userA').send_keys(username)
            driver.find_element_by_id('passwordA').send_keys(password)
    
        # 注意:传的参数名称要与yaml文件对应
        # 在yaml数据中文件中采用对象(键值对)的方式来定义数据内容
        @file_data('../user1.yaml')
        def test_yaml02(self, username, password):
            driver = self.driver
            driver.find_element_by_id('userA').send_keys(username)
            driver.find_element_by_id('passwordA').send_keys(password)
    
    
    if __name__ == '__main__':
        unittest.main()
    
    

    注意:file_date 装饰器,可以直接读取yaml和json文件

在unittest框架接口测试中,yaml文件中上一个接口的返回值在下一个接口的data中作为参数的情况下,可以按照以下方法进行编写:

  1. 在yaml文件中,为每个接口定义一个唯一的标识符或名称,以区分不同的接口。
  2. 在每个接口的定义中,使用“$ref”关键字引用上一个接口的返回值,将其作为本接口的参数。

例如,假设上一个接口的名称为“interface1”,返回值为“result”,下一个接口的名称为“interface2”,需要使用上一个接口的返回值作为参数,则可以按照以下方式编写yaml文件:

interface1:
  url: /api/test1
  method: post
  body:
    username: testuser
    password: testpass
  validate:
    - eq: [status_code, 200]
  store:
    - result

interface2:
  url: /api/test2
  method: post
  body:
    data: {"$ref": "#/interface1/result"}
  validate:
    - eq: [status_code, 200]

在上述示例中,我们定义了两个接口“interface1”和“interface2”。在“interface1”中,我们发送了一个post请求,将响应结果存储在“result”中。在“interface2”中,我们发送了另一个post请求,并将“$ref”关键字用于引用“interface1”中存储的“result”参数,以便在请求体中使用。

使用上述方法,您可以在yaml文件中轻松地引用上一个接口的返回值,并将其用作下一个接口的参数。希望这个例子对您有所帮助!