Flask 端点在执行时返回状态 400 就好了
Flask Endpoint Returning Status 400 While Executing Just Fine
我目前正在为一个函数编写单元测试,该函数处理 JSON 过滤器字符串以使用 flask-csv
构建 CSV 文件。当我在应用程序中测试该功能时,它运行良好,使用正确的过滤器触发下载,并以预期格式返回文件。
检查 response.data
中的输出结果也很好,但是当 运行 测试时我一直得到 BadRequest (400)
。
这将是端点函数:
csv-download.py
import json
import logging
import flask_csv
import pandas as pd
from flask import Blueprint
from jinja2 import Template
from pydantic import ValidationError
from models import CSVModel
home_blueprint = Blueprint("home", __name__, url_prefix="/")
@home_blueprint.route("csv_download", methods=["GET", "POST"])
def download_csv():
filter_str = request.args.get("filters")
content = request.args.get("content")
try:
model = CSVModel(csv_fliters=filter_str, csv_content=content)
except ValidationError as e:
raise BadInputException(e.json())
filters = json.loads(filter_str)
with open(
"bq_queries/myquery.bq", "r", encoding="utf-8"
) as file:
query_string = file.read()
query = Template(query_string)
# this function is replaced by a mock.patch in the test
data = load_from_query(apply_filters(query, filters, "None"), client)
today = pd.Timestamp.today().strftime("%Y%m%d")
start = pd.to_datetime(filters["order_date"][0]).strftime("%Y%m%d")
end = pd.to_datetime(filters["order_date"][1]).strftime("%Y%m%d")
response = flask_csv.send_csv(
data.to_dict(orient="records"),
f"{today}_{start}_until_{end}_{content}.csv".format(),
list(data.columns),
)
return response
这个函数是这样测试的:
test_csv_download.py
import pytest
from flask.testing import FlaskClient
from unittest.mock import patch
@patch('customer_feedback_hub.home.views.load_from_query')
def test_csv_download_(mock_load, client: FlaskClient) -> None:
"""
Test verifying that the CSV-Download Endpoint works.
"""
import pandas as pd
import json
mock_load.return_value = pd.DataFrame({'A': [1,2], 'B': [3,4]})
test_filters = {'subentity_id': 1, 'order_date': ['2019-10-30', '2019-10-31']}
suffix = "test"
dl_filters = json.dumps(test_filters)
response = client.get("/csv_download" +
"?filters={}&content={}".format(dl_filters, suffix))
# response format taken directly from:
# https://github.com/Shir0kamii/Flask-CSV/blob/master/test_flask_csv.py
expected = b"""A,B
1,3
2,4
""".replace(b'\n', b"\r\n")
response.data == expected
assert response.status_code == 200
测试失败的消息:
====================================================================== FAILURES =======================================================================
_________________________________________________________________ test_csv_download_ __________________________________________________________________
mock_load = <MagicMock name='load_from_query' id='139751143251392'>, client = <FlaskClient <Flask 'customer_feedback_hub.app'>>
@patch('customer_feedback_hub.home.views.load_from_query')
def test_csv_download_(mock_load, client: FlaskClient) -> None:
"""
Test verifying that the CSV-Download Endpoint works.
"""
import pandas as pd
import json
mock_load.return_value = pd.DataFrame({'A': [1,2], 'B': [3,4]})
test_filters = {'subentity_id': 1, 'order_date': ['2019-10-30', '2019-10-31']}
suffix = "test"
# start = pd.to_datetime(test_filters["order_date"][0]).strftime("%Y%m%d")
# end = pd.to_datetime(test_filters["order_date"][1]).strftime("%Y%m%d")
dl_filters = json.dumps(test_filters)
response = client.get("/csv_download" +
"?filters={}&content={}".format(dl_filters, suffix))
# response format taken directly from:
# https://github.com/Shir0kamii/Flask-CSV/blob/master/test_flask_csv.py
expected = b"""A,B
1,3
2,4
""".replace(b'\n', b"\r\n")
response.data == expected
> assert response.status_code == 200
E assert 400 == 200
E -400
E +200
tests/home/test_views.py:79: AssertionError
此外,为了完整起见,在原始函数中使用了 CSVModel
的定义,我用它来验证字符串确实可以加载为 JSON 字符串
models.py
import json
from pydantic import BaseModel, Extra, NoneStr, validator
class CSVModel(BaseModel):
"""
Example Pydantic model for validating json
"""
csv_filters: str
csv_content: NoneStr = None
class Config:
extra = Extra.forbid
@validator("csv_filters")
def filters_are_json(cls, v):
try:
dic = json.loads(v)
dic.items()
except Exception:
raise ValueError("No JSON!")
也许我遗漏了一些明显的东西,但我很乐意看到另一双眼睛。
你有
response.data == expected
但你可能想要
assert response.data == expected
我怀疑断言会失败并告诉你更多。 :)
我目前正在为一个函数编写单元测试,该函数处理 JSON 过滤器字符串以使用 flask-csv
构建 CSV 文件。当我在应用程序中测试该功能时,它运行良好,使用正确的过滤器触发下载,并以预期格式返回文件。
检查 response.data
中的输出结果也很好,但是当 运行 测试时我一直得到 BadRequest (400)
。
这将是端点函数:
csv-download.py
import json
import logging
import flask_csv
import pandas as pd
from flask import Blueprint
from jinja2 import Template
from pydantic import ValidationError
from models import CSVModel
home_blueprint = Blueprint("home", __name__, url_prefix="/")
@home_blueprint.route("csv_download", methods=["GET", "POST"])
def download_csv():
filter_str = request.args.get("filters")
content = request.args.get("content")
try:
model = CSVModel(csv_fliters=filter_str, csv_content=content)
except ValidationError as e:
raise BadInputException(e.json())
filters = json.loads(filter_str)
with open(
"bq_queries/myquery.bq", "r", encoding="utf-8"
) as file:
query_string = file.read()
query = Template(query_string)
# this function is replaced by a mock.patch in the test
data = load_from_query(apply_filters(query, filters, "None"), client)
today = pd.Timestamp.today().strftime("%Y%m%d")
start = pd.to_datetime(filters["order_date"][0]).strftime("%Y%m%d")
end = pd.to_datetime(filters["order_date"][1]).strftime("%Y%m%d")
response = flask_csv.send_csv(
data.to_dict(orient="records"),
f"{today}_{start}_until_{end}_{content}.csv".format(),
list(data.columns),
)
return response
这个函数是这样测试的:
test_csv_download.py
import pytest
from flask.testing import FlaskClient
from unittest.mock import patch
@patch('customer_feedback_hub.home.views.load_from_query')
def test_csv_download_(mock_load, client: FlaskClient) -> None:
"""
Test verifying that the CSV-Download Endpoint works.
"""
import pandas as pd
import json
mock_load.return_value = pd.DataFrame({'A': [1,2], 'B': [3,4]})
test_filters = {'subentity_id': 1, 'order_date': ['2019-10-30', '2019-10-31']}
suffix = "test"
dl_filters = json.dumps(test_filters)
response = client.get("/csv_download" +
"?filters={}&content={}".format(dl_filters, suffix))
# response format taken directly from:
# https://github.com/Shir0kamii/Flask-CSV/blob/master/test_flask_csv.py
expected = b"""A,B
1,3
2,4
""".replace(b'\n', b"\r\n")
response.data == expected
assert response.status_code == 200
测试失败的消息:
====================================================================== FAILURES =======================================================================
_________________________________________________________________ test_csv_download_ __________________________________________________________________
mock_load = <MagicMock name='load_from_query' id='139751143251392'>, client = <FlaskClient <Flask 'customer_feedback_hub.app'>>
@patch('customer_feedback_hub.home.views.load_from_query')
def test_csv_download_(mock_load, client: FlaskClient) -> None:
"""
Test verifying that the CSV-Download Endpoint works.
"""
import pandas as pd
import json
mock_load.return_value = pd.DataFrame({'A': [1,2], 'B': [3,4]})
test_filters = {'subentity_id': 1, 'order_date': ['2019-10-30', '2019-10-31']}
suffix = "test"
# start = pd.to_datetime(test_filters["order_date"][0]).strftime("%Y%m%d")
# end = pd.to_datetime(test_filters["order_date"][1]).strftime("%Y%m%d")
dl_filters = json.dumps(test_filters)
response = client.get("/csv_download" +
"?filters={}&content={}".format(dl_filters, suffix))
# response format taken directly from:
# https://github.com/Shir0kamii/Flask-CSV/blob/master/test_flask_csv.py
expected = b"""A,B
1,3
2,4
""".replace(b'\n', b"\r\n")
response.data == expected
> assert response.status_code == 200
E assert 400 == 200
E -400
E +200
tests/home/test_views.py:79: AssertionError
此外,为了完整起见,在原始函数中使用了 CSVModel
的定义,我用它来验证字符串确实可以加载为 JSON 字符串
models.py
import json
from pydantic import BaseModel, Extra, NoneStr, validator
class CSVModel(BaseModel):
"""
Example Pydantic model for validating json
"""
csv_filters: str
csv_content: NoneStr = None
class Config:
extra = Extra.forbid
@validator("csv_filters")
def filters_are_json(cls, v):
try:
dic = json.loads(v)
dic.items()
except Exception:
raise ValueError("No JSON!")
也许我遗漏了一些明显的东西,但我很乐意看到另一双眼睛。
你有
response.data == expected
但你可能想要
assert response.data == expected
我怀疑断言会失败并告诉你更多。 :)