Python 3.x 如何测试在flask/flask restx中接受解析器输入的GET方法?
我正在使用制作一个flask应用程序,并通过以下方式从用户处获取输入:Python 3.x 如何测试在flask/flask restx中接受解析器输入的GET方法?,python-3.x,unit-testing,flask,get,pytest,Python 3.x,Unit Testing,Flask,Get,Pytest,我正在使用制作一个flask应用程序,并通过以下方式从用户处获取输入: from flask_restx import Resource, reqparse from .services.calculator import DimensionCalculator parser = reqparse.RequestParser() parser.add_argument("dimensions", type=float, required
from flask_restx import Resource, reqparse
from .services.calculator import DimensionCalculator
parser = reqparse.RequestParser()
parser.add_argument("dimensions", type=float,
required=True,
action='split',
help="Dimensions of the rectangle (in meters)")
parser.add_argument("angle_inclination", type=float,
required=True,
action='append',
help="Angle of inclination of the Dachfläche (Neigung)")
@ns.route("/output")
class UserOutput(Resource):
@ns.expect(parser, validation=True)
def get(self):
args = parser.parse_args()
return DimensionCalculator.inputs(**args)
from .parser_impl import parser
from .dimension_calculator import DimensionCalculator
class Config(object):
parser_impl = parser
calculator = DimensionCalculator
@staticmethod
def configure_dimension_calculator_impl(impl):
Config.calculator = impl
@staticmethod
def configure_parser_impl(impl):
Config.parser_impl = impl
@staticmethod
def get_dimension_calculator_impl():
return Config.calculator
@staticmethod
def get_parser_impl():
return Config.parser_impl
其中,ns
是我定义的名称空间,DimensionCalculator的简化版本。输入是:
class DimensionCalculator:
def inputs(**user_input):
installation_place = user_input['installation_place']
num_rectangles = user_input['num_rectangles']
dimensions = user_input['dimensions']
angle_inclination = user_input['angle_inclination']
alignment = user_input['alignment']
direction = user_input['direction']
vendor = user_input['vendor']
output = {
"installation_place": installation_place,
"num_rectangles": num_rectangles,
"area_shape": area_shape,
"vendor": vendor
}
return output
我正在使用。我已经为所有类和方法编写了测试,唯一无法测试的是GET
方法,该方法在UserOutput
中定义。有没有办法测试GET
方法
非常感谢您的帮助。考虑到单元测试标签,我将介绍我提出的如何在完全隔离的情况下进行测试的方法。基本上,get
方法对依赖项进行两次函数调用,因此在单元意义上,您必须检查是否确实进行了这些调用,以及断言参数,对吗
本示例中的项目结构:
+---Project
| |
| | __init__.py
| | config.py
| | dimension_calculator.py
| | parser_impl.py
| | user_output.py
| | user_output_test.py
因此,为了简单起见,一切都是平面的
最重要的是,您必须将UserOutput
模块与依赖项分离。您不应该像这样硬编码依赖项:
from .services.calculator import DimensionCalculator
假设,DimensionCalculator
可能包含不应在测试范围内的复杂业务逻辑。下面是UserOutput
模块的外观:
from flask_restx import Resource, Api
from flask import Flask
from .config import Config
app = Flask(__name__)
api = Api(app)
ns = api.namespace('todos', description='TODO operations')
@ns.route("/output")
class UserOutput(Resource):
@ns.expect(Config.get_parser_impl(), validation=True)
def get(self):
args = Config.get_parser_impl().parse_args()
return Config.get_dimension_calculator_impl().inputs(**args)
if __name__ == '__main__':
app.run(debug=True)
如您所见,“外部”依赖项现在可以很容易地进行存根(这是称为依赖项注入的常见模式的一部分)。配置模块如下所示:
from flask_restx import Resource, reqparse
from .services.calculator import DimensionCalculator
parser = reqparse.RequestParser()
parser.add_argument("dimensions", type=float,
required=True,
action='split',
help="Dimensions of the rectangle (in meters)")
parser.add_argument("angle_inclination", type=float,
required=True,
action='append',
help="Angle of inclination of the Dachfläche (Neigung)")
@ns.route("/output")
class UserOutput(Resource):
@ns.expect(parser, validation=True)
def get(self):
args = parser.parse_args()
return DimensionCalculator.inputs(**args)
from .parser_impl import parser
from .dimension_calculator import DimensionCalculator
class Config(object):
parser_impl = parser
calculator = DimensionCalculator
@staticmethod
def configure_dimension_calculator_impl(impl):
Config.calculator = impl
@staticmethod
def configure_parser_impl(impl):
Config.parser_impl = impl
@staticmethod
def get_dimension_calculator_impl():
return Config.calculator
@staticmethod
def get_parser_impl():
return Config.parser_impl
最后,但并非最不重要的一点是,我们将在其中存根依赖项并注入它们:
from .user_output import UserOutput
from flask import Flask
from .config import Config
class ParserStub(object):
parse_args_call_count = 0
@staticmethod
def parse_args():
ParserStub.parse_args_call_count = ParserStub.parse_args_call_count + 1
return {'parser_stub': 2}
class DimensionCalculatorStub(object):
inputs_call_count = 0
@staticmethod
def inputs(**args):
DimensionCalculatorStub.inputs_call_count = DimensionCalculatorStub.inputs_call_count + 1
return {'stub': 1}
app = Flask(__name__)
def test_user_request_get():
with app.test_request_context():
# given
Config.configure_dimension_calculator_impl(DimensionCalculatorStub)
Config.configure_parser_impl(ParserStub)
uo = UserOutput()
# when
uo.get()
# then
assert DimensionCalculatorStub.inputs_call_count == 1
assert ParserStub.parse_args_call_count == 1
# assert arguments as well!
就我而言,考试通过了。缺少的一件事是参数的验证
为了完整起见,我还将包括DimensionCalculator和解析器本身,尽管它们与您的示例中完全相同。我只对它们进行了模块化:
from flask_restx import reqparse
parser = reqparse.RequestParser()
parser.add_argument("dimensions", type=float,
required=True,
action='split',
help="Dimensions of the rectangle (in meters)")
parser.add_argument("angle_inclination", type=float,
required=True,
action='append',
help="Angle of inclination of the Dachfläche (Neigung)")
以及尺寸_calculator.py:
class DimensionCalculator:
@staticmethod
def inputs(**user_input):
installation_place = user_input['installation_place']
num_rectangles = user_input['num_rectangles']
dimensions = user_input['dimensions']
angle_inclination = user_input['angle_inclination']
alignment = user_input['alignment']
direction = user_input['direction']
vendor = user_input['vendor']
output = {
"installation_place": installation_place,
"num_rectangles": num_rectangles,
"area_shape": "EMPTY",
"vendor": vendor
}
return output
重要肯定有专门的框架用于此类存根/模拟的准备和配置(例如:)。我只是想介绍一下概念和最简单的方法