【问题标题】:Flask click command unittests - how to use testing app with "with_appcontext" decorator?Flask click command unittests - 如何使用带有“with_appcontext”装饰器的测试应用程序?
【发布时间】:2017-06-08 06:42:10
【问题描述】:

我不知道如何在使用with_app_context 装饰器进行单元测试(使用 pytest)flask cli 命令(单击)时正确使用测试应用程序版本。此装饰器将 pytest 固定应用程序替换为“正常”的开发应用程序。我使用应用工厂模式。

我的简化版命令如下所示(注意@with_appcontext):

@click.command()
@click.option('--username', prompt='Username')
@click.option('--email', prompt='User E-Mail')
@click.option('--password', prompt='Password', confirmation_prompt=True, hide_input=True)
@with_appcontext  # from flask.cli import with_appcontext
def createsuperuser(username, email, password):
    user = User(
        username=username,
        email=email,
        password=password,
        active=True,
        is_admin=True,
    )
    user.save()

没有@with_appcontext 单元测试工作得很好(他们让应用程序被 pytest 注入),但命令本身没有,因为它需要一个应用程序上下文。

我提取的pytest代码:

# pytest fixtures
@pytest.yield_fixture(scope='function')
def app():
    """An application for the tests."""
    _app = create_app(TestConfig)
    ctx = _app.test_request_context()
    ctx.push()

    yield _app

    ctx.pop()


@pytest.yield_fixture(scope='function')
def db(app):
    """A database for the tests."""
    _db.app = app
    with app.app_context():
        _db.create_all()

    yield _db

    # Explicitly close DB connection
    _db.session.close()
    _db.drop_all()


@pytest.mark.usefixtures('db')
class TestCreateSuperUser:
    # db fixture uses app fixture, works the same if app was injected here as well
    def test_user_is_created(self, cli_runner, db):
        result = cli_runner.invoke(
            createsuperuser,
            input='johnytheuser\nemail@email.com\nsecretpass\nsecretpass'
        )
        assert result.exit_code == 0
        assert 'SUCCESS' in result.output
        # etc.

我所有使用appdb 夹具的测试除了这些装饰的夹具外都可以正常工作。我不确定应该如何解决这个设置应用程序本身的with_appcontext 装饰器。

提前感谢您的任何提示。

【问题讨论】:

    标签: python unit-testing flask command-line-interface pytest


    【解决方案1】:

    灵感来自https://github.com/pallets/flask/blob/master/tests/test_cli.py#L254

    from flask.cli import ScriptInfo
    
        @pytest.fixture
        def script_info(app):
            return ScriptInfo(create_app=lambda info: app)
    

    在你的测试中:

    def test_user_is_created(self, cli_runner, db, script_info):
        result = cli_runner.invoke(
            createsuperuser,
            input='johnytheuser\nemail@email.com\nsecretpass\nsecretpass',
            obj=obj,
        )
    

    【讨论】:

      【解决方案2】:

      接受的答案帮助我找到了解决方案,但没有开箱即用。如果其他人有类似的问题,这对我有用

      @pytest.fixture(scope='session')
      def script_info(app):
          return ScriptInfo(create_app=lambda:  app)
      
      def test_user_is_created(self, cli_runner, db, script_info):
          result = cli_runner.invoke(
              createsuperuser,
              input='johnytheuser\nemail@email.com\nsecretpass\nsecretpass',
              obj=script_info,
          )
      

      【讨论】:

        【解决方案3】:

        我在测试我的一个烧瓶命令时遇到了同样的问题。尽管您的方法有效,但我认为在这里查看烧瓶文档很有价值: https://flask.palletsprojects.com/en/1.1.x/testing/#testing-cli-commands

        Flask 有自己的 cli 命令测试运行器,它可能已经修复了我们的内置问题。因此,除了使用 lambda 修补 create_app 函数之外,您还可以只使用 app.test_cli_runner() ,它开箱即用。

        【讨论】:

          猜你喜欢
          • 2014-02-16
          • 1970-01-01
          • 2013-07-21
          • 1970-01-01
          • 2016-01-02
          • 2021-12-20
          • 1970-01-01
          • 2020-05-19
          • 2019-11-28
          相关资源
          最近更新 更多