如何编写干净的 pytest 链 api 测试
How to write clean pytest chain api tests
python 的新手,我对此感到困惑。我几乎无法在网上的任何地方找到明确和正确的答案。老实说,我觉得自己很愚蠢,因为这是一项非常基本的 python 技能。
我的问题:
我的任务是编写链接在一起的异步 api 请求的 python 测试套件。我需要触发请求,保存响应中的值 json,然后将这些值传递给后续请求。
下面列出了我希望测试执行的操作,以及根据我编写测试文件的方式我希望它执行的操作:
- 发送
GET
到/users
端点
- 首先将响应负载中的
customerId
保存为 customer_id
- 将
POST
发送到 /customer/{customer_id}/addresses
端点以创建新的客户地址
- 将响应负载中的
addressId
保存为 address_id
- 将
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 已经做得很好),您需要将此测试分解为多个案例,但模拟您未明确测试的数据每个阶段。
python 的新手,我对此感到困惑。我几乎无法在网上的任何地方找到明确和正确的答案。老实说,我觉得自己很愚蠢,因为这是一项非常基本的 python 技能。
我的问题: 我的任务是编写链接在一起的异步 api 请求的 python 测试套件。我需要触发请求,保存响应中的值 json,然后将这些值传递给后续请求。
下面列出了我希望测试执行的操作,以及根据我编写测试文件的方式我希望它执行的操作:
- 发送
GET
到/users
端点 - 首先将响应负载中的
customerId
保存为customer_id
- 将
POST
发送到/customer/{customer_id}/addresses
端点以创建新的客户地址 - 将响应负载中的
addressId
保存为address_id
- 将
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 已经做得很好),您需要将此测试分解为多个案例,但模拟您未明确测试的数据每个阶段。