首页 > 解决方案 > 创建自定义“测试”命令以运行 Flask 应用程序的测试套件

问题描述

我们正在使用一些自定义命令扩展 Flask-cli。该命令test是其中之一:

# run.py: specified by FLASK_APP
# This is the Flask application object
app = create_app(os.getenv('FLASK_ENV') or 'default')

@app.cli.command()
def test():
    """Run the unit tests."""
        
    tests = unittest.TestLoader().discover('tests')

    test_runner = unittest.TextTestRunner()
    test_runner.run(tests)

然而,一个典型的测试(使用 Python 的内置 unittest 模块)看起来像这样,它基于此处描述的样式。

# some-tests.py: unittest-based test case.
class SomeTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()

    def tearDown(self):
        self.app_context.pop()

    def test_load(self):
        pass

我显然在这里遇到了一个反模式:我已经使用 default( development) 配置初始化了一个烧瓶对象,因为我需要它用于@app.cli.command()装饰器,这一切都发生在run.py. 但是,一旦我在其中运行测试 setUp 函数,some-tests.py我就必须以某种方式使用该配置获取一个 Flask 对象,例如,通过使用现在发生testing的配置重新创建一个 Flask 应用程序。testing

我想知道如何实现一个flask-cli测试命令,其中只Flask创建一个对象,该对象在各种测试用例中重复使用,而无需testing在我flask test在命令行上运行之前明确设置环境。

标签: python-3.xtestingflaskflask-cli

解决方案


我不确定这个答案是否符合您的要求,但这就是我尝试解决这个问题的方式。不幸的是,如果您想在 Flask 中使用默认的 CLI 界面,那么您create_app只需调用flask test命令即可。你可以做的是尝试使用pytest. 它允许您创建可以跨多个测试用例使用的夹具。例如,在您的tests包中创建名为conftest.py并声明一些默认装置的文件,如下所示:

@pytest.fixture
def app():
    return create_app('testing')


@pytest.fixture
def client(app):
    return app.test_client()


@pytest.fixture
def database(app):
    _db.app = app

    with app.app_context():
        _db.create_all()

    yield _db

    _db.session.close()
    _db.drop_all()

然后在您的测试用例文件(例如 test_login.py)中,您可以像这样使用这些固定装置:

# Notice argument names are the same as name of our fixtures
# You don't need to import fixtures to this file - pytest will  
# automatically recognize fixtures for you
def test_registration(app, client):
    response = client.post(
        '/api/auth/login',
        json={
            'username': 'user1',
            'password': '$dwq3&jNYGu'
        })
    assert response.status_code == 200
    json_data = response.get_json()
    assert json_data['access_token']
    assert json_data['refresh_token']

这种方法最好的一点是您不需要创建setUptearDown方法。然后您可以test为您的应用创建 cli 命令:

import pytest

@app.cli.command()
def test():
    '''
    Run tests.
    '''
    pytest.main(['--rootdir', './tests'])

并这样称呼它flask test


推荐阅读