2016-04-15 49 views
2

我測試的燒瓶中的應用與py.test用下面的代碼:保留響應上下文測試燒瓶應用與pytest

response = flask_app_test_client.post('/users', data=json.dumps(user)) 
assert response.status_code == 201 
assert response.content_type == 'application/json' 
assert isinstance(response.json, dict) 
assert set(response.json.keys()) >= {'id', 'status', 'created_at', 'updated_at'} 
assert response.json['name'] == user['name'] 
assert response.json['status'] == 'pending' 

當某些斷言失敗,我得到這樣的:

  response = test_client.post('/users', data=json.dumps(user)) 
    >  assert response.status_code == 201 
    E  assert 400 == 201 
    E  + where 400 = <JSONResponse streamed [400 BAD REQUEST]>.status_code 
    ============== 1 failed, 3 passed in 0.10 seconds =================== 

我做了很多TDD,所以我期望我的測試在開發過程中經常失敗。我的問題是斷言錯誤消息是沒有其餘的響應數據(正文,標題等)沒用。

如何打印每個失敗斷言的回覆摘要?

+0

不太確定爲什麼你認爲你需要這裏的身體,它只會是一個400錯誤消息。你知道請求的正文和標題是什麼,你做到了。 – davidism

+0

@davidism我只在輸出中得到response.status_code是400,但我沒有得到響應正文中的錯誤描述。例如: – pablomolnar

+0

例如:{「errors」:[「username is already taken」,「email is required」]}在響應正文中。理想情況下,當斷言失敗時,我希望完全轉儲請求和響應(頭文件+主體)。 – pablomolnar

回答

0

Assert statement graamar

assert response.status_code == 201, "Anything you want"

你可以只要你想詳細。您也可以使用UnitTest的helper methods - 套件,但不包含通過此位濫用的測試用例類 - https://github.com/nose-devs/nose2/blob/master/nose2/tools/such.py#L34

+0

這需要手動爲每個測試請求中的某個斷言添加額外的輸出。 – davidism

+0

的確,現在我在每個斷言中添加response.json(),但似乎並不正確。我不能只是增強assert以打印自定義的東西?我很確定我在這裏錯過了一些東西...... – pablomolnar

+0

@pablomolnar我的歉意,在截止日期前工作,誤解了你的問題。如果只是這個特定的用例,可能是'try {assert block},但AssertionError:print(more.data);提高'? – David

0

我想出了兩種不同的解決方案。

解決方案#1:try/catch語句

try: 
    assert response.status_code == 201 
    assert response.content_type == 'application/json' 
    assert isinstance(response.json, dict) 
    assert set(response.json.keys()) >= {'id', 'status', 'created_at', 'updated_at'} 
    assert response.json['name'] == user['name'] 
    assert response.json['status'] == 'pending' 
except AssertionError as e: 
    except AssertionError as e: 
    raise ResponseAssertionError(e, response) 

class ResponseAssertionError(AssertionError): 
    def __init__(self, e, response): 
     response_dump = "\n + where full response was:\n" \ 
         "HTTP/1.1 {}\n" \ 
         "{}{}\n".format(response.status, response.headers, response.json) 

     self.args = (e.args[0] + response_dump,) 

解決方案2:不需要的try/catch(如果再版太長,有時被切斷......)

擴展和覆蓋瓶響應對象

import json 
class JSONResponse(Response): 

    def __repr__(self): 
     headers = {} 
     while len(self.headers) > 0: 
      tuple_ = self.headers.popitem() 
      headers[tuple_[0]] = tuple_[1] 

     data = { 
      'status': self.status, 
      'headers': headers, 
      'body': self.json 
     } 
     return json.dumps(data) 

@pytest.fixture(scope='session') 
    def test_client(flask_app): 
     flask_app.response_class = JSONResponse 
     return flask_app.test_client() 
+0

出於好奇你喜歡哪種?第一種形式似乎更理想,因爲您不會更改應用程序代碼以使測試輸出有用,但似乎更清晰,然後必須包裝測試。 – David