如何编写干净的 pytest 链 api 测试

How to write clean pytest chain api tests

python 的新手,我对此感到困惑。我几乎无法在网上的任何地方找到明确和正确的答案。老实说,我觉得自己很愚蠢,因为这是一项非常基本的 python 技能。

我的问题: 我的任务是编写链接在一起的异步 api 请求的 python 测试套件。我需要触发请求,保存响应中的值 json,然后将这些值传递给后续请求。

下面列出了我希望测试执行的操作,以及根据我编写测试文件的方式我希望它执行的操作:

  1. 发送GET/users端点
  2. 首先将响应负载中的 customerId 保存为 customer_id
  3. POST 发送到 /customer/{customer_id}/addresses 端点以创建新的客户地址
  4. 将响应负载中的 addressId 保存为 address_id
  5. PUT 发送到 /orders/{customer_id} 端点以使用步骤 #3 中的 address_id 更新订单。

示例代码: (这与我机器上的代码相同,但我用假信息清理了文件。

import requests
import json

    def first_request_get(self):
        url = 'https://api.example.net/users'

        headers = {'Content-Type': 'application/json',
                   'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
                   }

        payload = {}

        resp = requests.get(url, headers=headers, data=json.dumps(payload))

        json_str = json.dumps(payload)

        resp_body = resp.json()
        customer_id = resp_body['customer'][0]['id']
        assert resp_body['customer'][0]['id'] is not None
        assert resp.status_code == 200
        return customer_id

    def second_request_post(self):
        customer_id = self.first_request_get()
        url = 'https://api.example.net/customers/{}/addresses'.format(customer_id)

        headers = {'Content-Type': 'application/json',
                   'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
                   }

        payload = {"address1": "285 Beandip Ln",
                   "city": "Lincoln",
                   "province": "Nebraska",
                   "zip": "68510",
                   }

        resp = requests.post(url, headers=headers, data=json.dumps(payload))

        resp_body = resp.json()
        address_id = resp_body['address']['id']
        print('address_id == ')
        print(address_id)

        assert resp.status_code == 200
        assert resp_body['address']['id'] is not None
        return address_id

    def third_request_put(self):
        address_id = self.second_request_post()
        customer_id = self.first_request_get()
        url = 'https://api.example.net/orders/{}'.format(customer_id)

        headers = {'Content-Type': 'application/json',
                   'Authorization': 'Bearer asdfasdfasdfasdfasdfasdfasdf'
                   }

        payload = {"address_id": address_id,
                   "next_charge_scheduled_at": "2022-01-31T00:00:00",
                   "price": 6.85,
                   "quantity": 2,
                   }

        resp = requests.put(url, headers=headers, data=json.dumps(payload))

        resp_body = resp.json()
        subscription_id = resp_body['order']['id']
        print('order_id == ')
        print(subscription_id)
        assert resp_body['order']['id'] is not None
        assert resp.status_code == 200
        return subscription_id

执行此测试文件的结果是以一种奇怪的顺序循环遍历文件,而不是按照我的预期执行。为什么我必须调用一个较早的函数来访问我已经从 json 中提取并分配给较早函数中的变量的变量?

遗憾的是,不建议以这种方式设计测试。 测试用例应该完全相互独立并且没有副作用。执行顺序无关紧要。 Pytest documentation 在其他来源中提到了这一点(并采取措施禁止违反这一原则)。 我还可以推荐 Glenford J Myers 的《软件测试的艺术》一书。

因此,要使此测试有效,您必须将其全部放在一个方法中... 如果您想更明确地说明故障点(即使 pytest 已经做得很好),您需要将此测试分解为多个案例,但模拟您未明确测试的数据每个阶段。