簡體   English   中英

使用 pytest 保留響應上下文測試燒瓶應用程序

[英]Preserve response context testing flask app with pytest

我正在使用 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"]} 理想情況下,我希望在斷言失敗時完整轉儲請求和響應(標頭 + 正文)。

如何打印每個失敗斷言的響應摘要?

斷言語句語法

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

您可以隨心所欲地詳細說明。 您還可以使用 UnitTest 的輔助方法套件 - 通過這種濫用而無需測試用例類 - https://github.com/nose-devs/nose2/blob/master/nose2/tools/such.py​​#L34

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

解決方案#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:不需要 try/catch(如果 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()

我知道這是一個較舊的問題,但 Pytest 有一個選項--pdb ,如果您的測試失敗,它會將您彈出到 PDB shell。 “環顧四周”的非常方便的方法,而不必將大量內容傳遞給異常消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM