使用pytest,如何在有和没有配置文件的情况下测试Flask应用程序的配置?

时间:2017-01-29 05:50:07

标签: python-3.x unit-testing flask pytest

我正在编写一个简单的烧瓶应用程序,并希望测试我的配置选项是否正常工作。

这是我的config.py:

import logging
import logging.handlers
import os


class BaseConfig(object):
    DEBUG = False
    TESTING = False
    ...


class DevelopmentConfig(BaseConfig):
    DEBUG = True
    TESTING = True
    ...


class TestingConfig(BaseConfig):
    DEBUG = False
    TESTING = True
    ...

config = {
    'development': 'app.config.DevelopmentConfig',
    'testing': 'app.config.TestingConfig',
    'default': 'app.config.BaseConfig'
}


def configure_app(app):
    config_name = os.environ.get('FLASK_CONFIGURATION', 'default')
    app.config.from_object(config[config_name])
    app.config.from_pyfile('config.py', silent=True)
    apikey = os.environ.get('TOKEN', None)
    if apikey:
        app.config['APIKEY'] = apikey

我在创建Flack对象后立即在configure_app中调用__init__.py

app = Flask(__name__)
configure_app(app)

config.py:

APIKEY = 'filesecret'
HOOKS = {'testpush': 'scripts/test.sh'}

我想要做的是能够使用py.test对各种配置选项进行单元测试。我目前的尝试是尝试使用mock_open,但配置会继续读取文件中的内容而不是跳过它。

class TestConfig:

    def setup(self):
        self.app = app.app
        self.app.config['TESTING'] = True

    def test_default(self, mocker):
        m = mocker.mock_open(read_data='')
        configure_app(self.app)
        assert self.app.config['APIKEY'] == "secret"

测试结果:

    def test_default(self, mocker):
        m = mocker.mock_open(read_data='')
        configure_app(self.app)
>       assert self.app.config['APIKEY'] == "secret"
E       assert 'filesecret' == 'secret'

当我不知道烧瓶内部时,我不知道该怎么做。有没有办法假冒/嘲笑文件?我希望能够编写存在的配置文件的各种测试用例,而不是存在,并且设置环境变量以确保保持优先级。

1 个答案:

答案 0 :(得分:0)

所以我认为这一切都错了。我查看了Flask的源代码,看到了他们如何测试他们的配置函数,他们只是用自己的环境变量实例化了一个新的Flask对象。

Flask project test_config.py

使用the context manager found on this stackoverflow question(目前是contextlib的底层答案)来设置我的环境变量,我得到了这一切。

最终测试:

@pytest.mark.parametrize(
    'envtoken, flask_conf, test_path, apikey, debug, testing', [
        ('', 'default', 'missing', 'secret', False, False),
        ('', 'development', 'missing', 'secret', True, True),
        ('', 'testing', 'missing', 'secret', False, True),
        ('', 'default', '../tests/data', 'filesecret', False, False),
        ('envsecret', 'default', '../tests/data/', 'envsecret', False, False)])
def test_config_app(envtoken, flask_conf, test_path, apikey, debug, testing):
    with set_env(DOCKERHOOK_TOKEN=envtoken, FLASK_CONFIGURATION=flask_conf):
        # app = Flask(__name__)
        base_path = get_app_base_path()
        instance_path = os.path.join(base_path, test_path)

        app = Flask(__name__,
                    instance_path=instance_path,
                    instance_relative_config=True)

        configure_app(app)

        assert app.config['APIKEY'] == apikey
        assert app.config['DEBUG'] == debug
        assert app.config['TESTING'] == testing