2016-04-15 50 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