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

问题描述 投票:2回答:2

我正在使用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'

当一些断言失败时,我得到这样的东西:

            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,所以我希望我的测试在开发过程中经常失败。我的问题是断言错误消息没有其余的响应数据(正文,标题等)是没用的。

我只在输出中得到response.status_code为400但我没有得到响应体中的错误描述:{"errors": ["username is already taken", "email is required"]}。理想情况下,当断言失败时,我希望完整转储请求和响应(标题+正文)。

如何在每个失败的断言上打印响应摘要?

python flask pytest
2个回答
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
投票

我提出了两种不同的解决方案。

解决方案#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,)

解决方案#2:不需要尝试/捕获(如果repr太长,有时会被切断......)

扩展和覆盖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)

    @pytest.fixture(scope='session')
    def test_client(flask_app):
        flask_app.response_class = JSONResponse
        return flask_app.test_client()
© www.soinside.com 2019 - 2024. All rights reserved.