最佳实践:自动化Web API测试

时间:2013-02-06 23:30:59

标签: python testing ckan web-api-testing

我用Python编写了一个程序,它使用两个不同的API来从两个不同的服务(CKAN和MediaWiki)获取数据。 特别是,有一个类Resource,它从上面提到的服务中请求数据并对其进行处理。

在某些时候,我得出结论,我的应用程序需要测试。 问题是我在网上和书中发现的所有例子都没有处理这种情况。

例如,在Resource类中我有一个方法:

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获取有关资源的数据并将其分配给对象。这很简单,但是......

我的问题是:如何测试这样的方法?我应该在这里测试什么?

我想到了将结果腌制(保存)到HDD的可能性。然后我可以在测试中加载它并与使用load_from_ckan()初始化的对象进行比较。但CKAN是社区驱动的平台,这种测试的行为将是不可预测的。

如果有任何关于自动化测试哲学的书籍(比如测试什么,不测试什么,如何使测试有意义等等),请给我一个链接。

3 个答案:

答案 0 :(得分:2)

通过任何测试,关键问题是 - 可能出错?

在您的情况下,看起来三个风险是:

  • 相关的网络API可能会停止工作。但是您已经使用assert r.ok
  • 检查了这一点
  • 您或其他人可能会在将来对代码进行错误的更改(例如,错误输入变量),这会对其造成破坏。
  • API可能会更改,因此它不再返回您需要的字段或格式。

感觉你可以为后两个编写一个相当简单的测试,具体取决于你实际依赖的API中的数据:例如,如果你期望JSON有一个名为“temperature”的字段,那就是一个浮点Celsius数字,你可以写一个调用你的函数的测试,然后检查self.temperature是'float'的一个实例,并且在一个合理的值范围内(-30到50?)。这应该让您确信API和您的功能都按设计工作。

答案 1 :(得分:1)

通常,如果要对某些外部服务进行测试,则需要使用模拟/虚拟对象来伪造外部服务的api。这必须在运行时通过方法的参数或类的构造函数或其他类型的间接来配置。另一个更复杂的选择是在测试期间使用补丁全局变量,例如“import requests; request.post = fake_post”,但这会产生更多问题。

例如,您的方法可以采用如下参数:

def load_from_ckan(self, post=requests.post):
    # ...
    r = post(url, timeout=config.ckan_request_timeout, data=data,
        headers=headers)
    # ...

然后在测试期间你会编写自己的帖子函数,返回json结果,你会看到从ckan回来。例如:

 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

在测试中构造结果比腌制结果和返回它们提供了更多的灵活性,因为您可以制作错误条件或专注于您的代码可能不会预期但您知道可能存在的特定格式。

总的来说,您可以看到这种情况有多复杂,所以如果您遇到重复错误或其他困难,我只会开始添加此类测试。这只需要维护更多的代码。

答案 2 :(得分:0)

此时,您可以测试CKAN的响应是否已正确解析。因此,您可以从CKAN中提取JSON并确保它返回包含您感兴趣的属性的数据。