2013-02-06 49 views
3

我已經用Python編寫了一個程序,它使用兩個不同的API來從兩個不同的服務(CKAN和MediaWiki)獲取數據。 特別是有一個類Resource,它從上述服務請求數據並處理它。最佳實踐:自動化Web API測試

在某些時候,我已經得出結論,我的應用程序需要測試。 問題是,我在網絡和書籍上找到的所有示例都不涉及這種情況。

例如,資源類中我有一個方法:

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是社區驅動的平臺,這種測試的行爲將是不可預測的。

如果有任何有關自動化測試哲學的書籍(比如測試什麼,不測試什麼,如何使測試有意義等),請給我一個鏈接。

回答

2

任何測試,關鍵問題的確是 - 什麼可能出錯?

在你的情況下,它看起來像三個風險:

  • 特定的Web API可能停止工作。但你已經檢查了這個,assert r.ok
  • 您或其他人可能會在將來對代碼進行錯誤更改(例如,將一個變量忽略),從而導致代碼被破壞。
  • API可能會更改,以便它不再返回所需的字段或格式。

感覺你可以爲後兩者編寫一個相當簡單的測試,具體取決於你實際依賴的API的數據:例如,如果你期望JSON有一個名爲「temperature 「這是一個浮點攝氏數,你可以編寫一個調用你的函數的測試,然後檢查self.temperature是'float'的一個實例,並且在一個合理的值範圍內(-30到50?)。這應該讓你確信,API和你的功能都按設計工作。

+0

檢查返回對象的屬性是一個好主意,謝謝!我只是檢查對象是否包含我在代碼中稍後使用的所有屬性。 –

0

此時,您可以測試來自CKAN的響應是否已正確解析。因此,您可以從CKAN中拉出JSON並確保其返回的數據包含您感興趣的屬性。

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 

構建結果在您的測試給你比酸洗結果,並將其送回,因爲你可以製造的錯誤條件或聚焦於特定格式的代碼可能不希望有更多的靈活性,但你知道可能存在。

總體而言,您可以看到這會變得多麼複雜,因此如果您遇到重複錯誤或其他困難,我只會開始添加此類測試。這將只需要更多的代碼來維護。