import contextlib import os import unittest from flask_env import MetaFlaskEnv class TestFlaskEnv(unittest.TestCase): @contextlib.contextmanager def with_env(self, **kwargs): """Context manager to set temporary environment variables and then remove when done""" # Set environment variables os.environ.update(kwargs) # Yield to caller yield # Delete set variables for key in kwargs.keys(): if key in os.environ: del os.environ[key] def _get_test_configuration(self, env_prefix='', env_load_all=False, **kwargs): """Helper to define a new configuration class using our MetaFlaskEnv""" return MetaFlaskEnv('TestConfiguration', (object, ), dict( ENV_PREFIX=env_prefix, ENV_LOAD_ALL=env_load_all, **kwargs )) def test_default_env_load_all(self): """A test to ensure that we load all environment variables by default""" # Configure an environment variable not defined on the configuration class with self.with_env(TEST_SETTING='true', DEFAULT_SETTING='set_by_env'): # Create our configuration object TestConfiguration = MetaFlaskEnv('TestConfiguration', (object, ), dict( DEFAULT_SETTING='set_in_class', )) # Assert that we only loaded defined settings from environment self.assertFalse(hasattr(TestConfiguration, 'TEST_SETTING')) self.assertEqual(TestConfiguration.DEFAULT_SETTING, 'set_by_env') def test_default_settings(self): """A test to ensure that if no environment variable is set, we get the default value that is set""" TestConfiguration = self._get_test_configuration(DEFAULT_SETTING='default_value') self.assertEqual(TestConfiguration.DEFAULT_SETTING, 'default_value') def test_override_from_env(self): """A test to ensure that an environment variable will override the default setting""" with self.with_env(DEFAULT_SETTING='set_by_env'): TestConfiguration = self._get_test_configuration(DEFAULT_SETTING='default_value') self.assertEqual(TestConfiguration.DEFAULT_SETTING, 'set_by_env') def test_only_set_on_env(self): """A test to ensure that a setting only defined by an environment variable is still available""" with self.with_env(NEW_SETTING='set_by_env'): # When configured to load all environment variables TestConfiguration = self._get_test_configuration(env_load_all=True) self.assertEqual(TestConfiguration.NEW_SETTING, 'set_by_env') # When configured to not load all environment variables TestConfiguration = self._get_test_configuration(env_load_all=False) self.assertFalse(hasattr(TestConfiguration, 'NEW_SETTING')) def test_env_prefix(self): """A test to ensure that the ENV_PREFIX setting functions as needed""" with self.with_env(TEST_DEFAULT_SETTING='set_by_env'): TestConfiguration = self._get_test_configuration(env_prefix='TEST_', DEFAULT_SETTING='default_value') self.assertEqual(TestConfiguration.DEFAULT_SETTING, 'set_by_env') def test_env_prefix_non_matching(self): """A test to ensure that the ENV_PREFIX setting does not allow non-matching settings in""" with self.with_env(DEFAULT_SETTING='set_by_env'): TestConfiguration = self._get_test_configuration(env_prefix='MYAPP_', DEFAULT_SETTING='default_value') self.assertEqual(TestConfiguration.DEFAULT_SETTING, 'default_value') def test_parsing_boolean(self): """A test to ensure that we properly parse booleans""" # DEV: We have to set the environment variable first, since they get loaded into the class on definition env = dict( IS_TRUE='true', IS_NOT_TRUE='true-ish', IS_FALSE='FALSE', IS_WACKY_FALSE='FaLSe', ) with self.with_env(**env): # DEV: Set `env_load_all=True` to keep from having to make default values for each variable TestConfiguration = self._get_test_configuration(env_load_all=True) self.assertEqual(TestConfiguration.IS_TRUE, True) self.assertEqual(TestConfiguration.IS_NOT_TRUE, 'true-ish') self.assertEqual(TestConfiguration.IS_FALSE, False) self.assertEqual(TestConfiguration.IS_WACKY_FALSE, False) def test_parsing_float(self): """A test to ensure that we properly parse floats""" env = dict( IS_FLOAT='12.5', TRAILING_DOT='12.', LEADING_DOT='.12', IS_NOT_FLOAT='This is 6.5', ) with self.with_env(**env): # DEV: Set `env_load_all=True` to keep from having to make default values for each variable TestConfiguration = self._get_test_configuration(env_load_all=True) self.assertEqual(TestConfiguration.IS_FLOAT, 12.5) self.assertEqual(TestConfiguration.TRAILING_DOT, 12.0) self.assertEqual(TestConfiguration.LEADING_DOT, 0.12) self.assertEqual(TestConfiguration.IS_NOT_FLOAT, 'This is 6.5') def test_parsing_int(self): """A test to ensure that we properly parse integers""" env = dict( IS_INT='12', IS_ZERO='0', IS_NOT_INT='12fa', ) with self.with_env(**env): # DEV: Set `env_load_all=True` to keep from having to make default values for each variable TestConfiguration = self._get_test_configuration(env_load_all=True) self.assertEqual(TestConfiguration.IS_INT, 12) self.assertEqual(TestConfiguration.IS_ZERO, 0) self.assertEqual(TestConfiguration.IS_NOT_INT, '12fa') if __name__ == '__main__': unittest.main()