【问题标题】:How to test a Connexion/Flask app?如何测试 Connexion/Flask 应用程序?
【发布时间】:2017-03-21 17:44:52
【问题描述】:

我正在使用Connexion 框架为Flask 构建一个微服务。我想使用 py.test 为我的应用程序编写测试。

pytest-flask 文档中,它说要在conftest.py 中创建一个固定装置,这样可以创建应用程序:

conftest.py

import pytest

from api.main import create_app


@pytest.fixture
def app():
    app = create_app()
    return app

在我的测试中,我使用了这样的client 夹具:

test_api.py

def test_api_ping(client):
    res = client.get('/status')
    assert res.status == 200

但是,当我运行 py.test 时,我收到以下错误消息:

==================================== ERRORS ====================================
_______________________ ERROR at setup of test_api_ping ________________________

request = <SubRequest '_monkeypatch_response_class' for <Function 'test_api_ping'>>
monkeypatch = <_pytest.monkeypatch.MonkeyPatch instance at 0x7f9f76b76518>

    @pytest.fixture(autouse=True)
    def _monkeypatch_response_class(request, monkeypatch):
        """Set custom response class before test suite and restore the original
        after. Custom response has `json` property to easily test JSON responses::
    
            @app.route('/ping')
            def ping():
                return jsonify(ping='pong')
    
            def test_json(client):
                res = client.get(url_for('ping'))
                assert res.json == {'ping': 'pong'}
    
        """
        if 'app' not in request.fixturenames:
            return
    
        app = request.getfuncargvalue('app')
        monkeypatch.setattr(app, 'response_class',
>                           _make_test_response_class(app.response_class))
E       AttributeError: 'App' object has no attribute 'response_class'

我怎样才能使py.test 工作?这是我的create_app 函数:

main.py

import connexion


def create_app():
    app = connexion.App(__name__, port=8002,)
    app.add_api('swagger.yaml')
    return app


if __name__ == "__main__":
    create_app().run()

【问题讨论】:

    标签: python flask swagger pytest connexion


    【解决方案1】:
    import pytest
    from json import JSONEncoder
    import pytest
    from connexion import App
    
    SWAGGER_PATH = "path_to_directory_that_containes_swagger_file"
    
    @pytest.fixture
    def app():
        app = App(__name__, specification_dir=SWAGGER_PATH)
        app.app.json_encoder = JSONEncoder
        app.add_api("swagger.yaml")
        app_client = app.app.test_client()
        return app_client
    
    
    def test_health(app) -> None:
        """
        :except: success
        """
        response = app.get("/health", content_type='application/json')
        assert response.status_code == 200
    

    更多信息请查看this

    【讨论】:

      【解决方案2】:

      使用夹具

      test_api.py

      import pytest
      import connexion
      
      flask_app = connexion.FlaskApp(__name__)
      flask_app.add_api('swagger.yml')
      
      
      @pytest.fixture(scope='module')
      def client():
          with flask_app.app.test_client() as c:
              yield c
      
      
      def test_health(client):
          response = client.get('/health')
          assert response.status_code == 200
      

      swagger.yml

      swagger: '2.0'
      info:
        title: My API
        version: '1.0'
      consumes:
        - application/json
      produces:
        - application/json
      schemes:
        - https
      paths:
        /health:
          get:
            tags: [Health]
            operationId: api.health
            summary: Health Check
            responses:
              '200':
                description: Status message from server describing current health
      

      api.py

      def health():
          return {'msg': 'ok'}, 200
      

      使用 Swagger 测试器

      使用swagger-tester的另一种解决方案:

      test_api.py

      from swagger_tester import swagger_test
      
      authorize_error = {
          'get': {
              '/health': [200],
          }
      }
      
      def test_swagger():
          swagger_test('swagger.yml', authorize_error=authorize_error)
      

      这个库很酷的地方在于您可以使用规范中提供的示例。但我认为 connexion.RestyResolver 不能开箱即用:您必须在每个端点指定 OperationId。

      【讨论】:

      • 这实际上对我有用一次。但是,现在又开始失败了,不知道为什么:E AttributeError: 'FlaskClient' object has no attribute 'response_class'
      • 我实际上将灯具命名为 app
      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2013-06-22
      相关资源
      最近更新 更多