简体   繁体   English

使用 pytest 保留响应上下文测试烧瓶应用程序

[英]Preserve response context testing flask app with pytest

I'm testing a flask application with py.test with the following code:我正在使用 py.test 使用以下代码测试烧瓶应用程序:

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'

When some assertion fails I'm getting something like this:当某些断言失败时,我会得到这样的信息:

            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 ===================

I do a lot of TDD so I expect my test fails frequently while developing.我做了很多 TDD,所以我希望我的测试在开发过程中经常失败。 My problem is the assertion error message is kind of useless without the rest of the response data (body, headers, etc).我的问题是断言错误消息在没有其余响应数据(正文、标题等)的情况下毫无用处。

I only get in the output that the response.status_code is 400 but I don't get the error description that is in the response body: {"errors": ["username is already taken", "email is required"]} .我只得到 response.status_code 为 400 的输出,但我没有得到响应正文中的错误描述: {"errors": ["username is already taken", "email is required"]} Ideally I would like a full dump of the request and response (headers + body) when an assertion fails.理想情况下,我希望在断言失败时完整转储请求和响应(标头 + 正文)。

How I can print a summary of the response on each failed assertion?如何打印每个失败断言的响应摘要?

Assert statement graamar 断言语句语法

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

You can be as verbose as you want.您可以随心所欲地详细说明。 You can also use UnitTest's suite of helper methods - without test case classes through this bit of abuse - https://github.com/nose-devs/nose2/blob/master/nose2/tools/such.py#L34您还可以使用 UnitTest 的辅助方法套件 - 通过这种滥用而无需测试用例类 - https://github.com/nose-devs/nose2/blob/master/nose2/tools/such.py​​#L34

I'm came up with two different solutions.我想出了两种不同的解决方案。

Solution #1: try/catch解决方案#1:尝试/捕获

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,)

Solution #2: no try/catch needed (if repr is too long sometimes is cut off...)解决方案#2:不需要 try/catch(如果 repr 太长有时会被切断......)

Extend and override Flask response object扩展和覆盖 Flask 响应对象

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)

and

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

I know this is an older question, but Pytest has an option --pdb that will pop you into a PDB shell should your test fail.我知道这是一个较旧的问题,但 Pytest 有一个选项--pdb ,如果您的测试失败,它会将您弹出到 PDB shell。 Very handy way to "just look around" rather than having to pass tons of stuff to an exception message. “环顾四周”的非常方便的方法,而不必将大量内容传递给异常消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM