Python 最佳实践:自动化web API测试
我用Python编写了一个程序,它使用两个不同的API从两个不同的服务(CKAN和MediaWiki)获取数据。 特别是,有一个类资源,它从上述服务请求数据并对其进行处理 在某种程度上,我得出结论,我的应用程序需要进行测试。 问题是,我在网上和书中找到的所有例子都不涉及这种情况 例如,在资源类中,我有一个方法:Python 最佳实践:自动化web API测试,python,testing,ckan,web-api-testing,Python,Testing,Ckan,Web Api Testing,我用Python编写了一个程序,它使用两个不同的API从两个不同的服务(CKAN和MediaWiki)获取数据。 特别是,有一个类资源,它从上述服务请求数据并对其进行处理 在某种程度上,我得出结论,我的应用程序需要进行测试。 问题是,我在网上和书中找到的所有例子都不涉及这种情况 例如,在资源类中,我有一个方法: def load_from_ckan(self): """ Get the resource specified by self.id
def load_from_ckan(self):
"""
Get the resource
specified by self.id
from config.ckan_api_url
"""
data = json.dumps({'id': self.id})
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
url = config.ckan_api_url + '/action/resource_show'
r = requests.post(url, timeout=config.ckan_request_timeout, data=data, headers=headers)
assert r.ok, r
resource = json.loads(r.content)
resource = resource["result"]
for key in resource:
setattr(self, key, resource[key])
load_from_ckan方法从ckan API获取关于资源的数据,并将其分配给对象。这很简单,但是
我的问题是:如何测试这样的方法?或我应该在这里测试什么?
我考虑了将结果保存到硬盘的可能性。然后我可以在测试中加载它,并与使用load_from_ckan()初始化的对象进行比较。但CKAN是社区驱动的平台,此类测试的行为将是不可预测的
如果有任何关于自动测试原理的书籍(如测试什么、不测试什么、如何使测试有意义等等),请给我一个链接。此时,您可以测试来自CKAN的响应是否被正确解析。因此,您可以从CKAN中提取JSON,并确保它返回的数据具有您感兴趣的属性。任何测试中,关键问题都是-会出什么问题 在您的情况下,这三种风险似乎是:
- 有问题的web API可能会停止工作。但是您已经用
检查过了assert r.ok
- 您或其他人将来可能会对代码进行错误更改(例如,错误键入变量),从而导致代码中断
- API可能会更改,从而不再返回所需的字段或格式
感觉上你可以为后两者编写一个相当简单的测试,这取决于你实际依赖的API数据:例如,如果你希望JSON有一个名为“temperature”的字段,它是一个浮点摄氏数,你可以编写一个调用你的函数的测试,然后检查self.temperature是否是“float”的一个实例,是否在合理的值范围内(-30到50?)。这将使您确信API和函数都在按设计工作。通常,如果您想针对这样的外部服务进行测试,您需要使用模拟/虚拟对象来伪造外部服务的API。这必须在运行时通过方法的参数或类的构造函数或其他类型的间接寻址进行配置。另一个更复杂的选项是在测试期间对全局进行修补,比如“import requests;request.post=false_post”,但这可能会产生更多问题 例如,您的方法可以采用如下参数:
def load_from_ckan(self, post=requests.post):
# ...
r = post(url, timeout=config.ckan_request_timeout, data=data,
headers=headers)
# ...
然后在测试过程中,您可以编写自己的post函数,返回从ckan返回的json结果。例如:
def mock_post(url, timeout=30, data='', headers=None):
# ... probably check input arguments
class DummyResponse:
pass
r = DummyResponse()
r.ok = True
r.content = json.dumps({'result': {'attr1': 1, 'attr2': 2}})
return r
在测试中构造结果比酸洗结果并返回结果要灵活得多,因为您可以捏造错误条件或专注于代码可能不期望但知道可能存在的特定格式
总的来说,您可以看到这可能会变得多么复杂,所以只有在您遇到重复错误或其他困难时,我才会开始添加此类测试。这只需要维护更多的代码。检查返回对象的属性是一个好主意,谢谢!我将只检查对象是否包含我稍后在代码中使用的所有属性。