1import os 2import unittest 3from decimal import Decimal, InvalidOperation 4import json 5 6try: 7 # python 3.4+ should use builtin unittest.mock not mock package 8 from unittest.mock import patch 9 from unittest import mock 10except ImportError: 11 from mock import patch 12 import mock 13 14import sys 15 16from envs import env 17 18class EnvTestCase(unittest.TestCase): 19 def setUp(self): 20 # Integer 21 os.environ.setdefault('VALID_INTEGER', '1') 22 os.environ.setdefault('INVALID_INTEGER', '["seven"]') 23 # String 24 os.environ.setdefault('VALID_STRING', 'seven') 25 # Boolean 26 os.environ.setdefault('VALID_BOOLEAN', 'True') 27 os.environ.setdefault('VALID_BOOLEAN_FALSE', 'false') 28 os.environ.setdefault('INVALID_BOOLEAN', 'seven') 29 # List 30 os.environ.setdefault('VALID_LIST', "['1','2','3']") 31 os.environ.setdefault('INVALID_LIST', "1") 32 # Tuple 33 os.environ.setdefault('VALID_TUPLE', "('True','FALSE')") 34 os.environ.setdefault('INVALID_TUPLE', '1') 35 # Dict 36 os.environ.setdefault('VALID_DICT', "{'first_name':'Suge'}") 37 os.environ.setdefault('INVALID_DICT', 'Aaron Rogers') 38 # Float 39 os.environ.setdefault('VALID_FLOAT', "5.0") 40 os.environ.setdefault('INVALID_FLOAT', '[5.0]') 41 # Decimal 42 os.environ.setdefault('VALID_DECIMAL', "2.39") 43 os.environ.setdefault('INVALID_DECIMAL', "FOOBAR") 44 45 def test_integer_valid(self): 46 self.assertEqual(1, env('VALID_INTEGER', var_type='integer')) 47 48 def test_integer_invalid(self): 49 with self.assertRaises(TypeError) as vm: 50 env('INVALID_INTEGER', var_type='integer') 51 52 def test_wrong_var_type(self): 53 with self.assertRaises(ValueError) as vm: 54 env('INVALID_INTEGER', var_type='set') 55 56 def test_string_valid(self): 57 self.assertEqual('seven', env('VALID_STRING')) 58 59 def test_boolean_valid(self): 60 self.assertEqual(True, env('VALID_BOOLEAN', var_type='boolean')) 61 62 def test_boolean_valid_false(self): 63 self.assertEqual(False, env('VALID_BOOLEAN_FALSE', var_type='boolean')) 64 65 def test_boolean_invalid(self): 66 with self.assertRaises(ValueError) as vm: 67 env('INVALID_BOOLEAN', var_type='boolean') 68 69 def test_list_valid(self): 70 self.assertEqual(['1', '2', '3'], env('VALID_LIST', var_type='list')) 71 72 def test_list_invalid(self): 73 with self.assertRaises(TypeError) as vm: 74 env('INVALID_LIST', var_type='list') 75 76 def test_tuple_valid(self): 77 self.assertEqual(('True', 'FALSE'), env('VALID_TUPLE', var_type='tuple')) 78 79 def test_tuple_invalid(self): 80 with self.assertRaises(TypeError) as vm: 81 env('INVALID_TUPLE', var_type='tuple') 82 83 def test_dict_valid(self): 84 self.assertEqual({'first_name': 'Suge'}, env('VALID_DICT', var_type='dict')) 85 86 def test_dict_invalid(self): 87 with self.assertRaises(SyntaxError) as vm: 88 env('INVALID_DICT', var_type='dict') 89 90 def test_float_valid(self): 91 self.assertEqual(5.0, env('VALID_FLOAT', var_type='float')) 92 93 def test_float_invalid(self): 94 with self.assertRaises(TypeError) as vm: 95 env('INVALID_FLOAT', var_type='float') 96 97 def test_decimal_valid(self): 98 self.assertEqual(Decimal('2.39'), env('VALID_DECIMAL', var_type='decimal')) 99 100 def test_decimal_invalid(self): 101 with self.assertRaises(ArithmeticError) as vm: 102 env('INVALID_DECIMAL', var_type='decimal') 103 104 def test_defaults(self): 105 self.assertEqual(env('HELLO', 5, var_type='integer'), 5) 106 self.assertEqual(env('HELLO', 5.0, var_type='float'), 5.0) 107 self.assertEqual(env('HELLO', [], var_type='list'), []) 108 self.assertEqual(env('HELLO', {}, var_type='dict'), {}) 109 self.assertEqual(env('HELLO', (), var_type='tuple'), ()) 110 self.assertEqual(env('HELLO', 'world'), 'world') 111 self.assertEqual(env('HELLO', False, var_type='boolean'), False) 112 self.assertEqual(env('HELLO', 'False', var_type='boolean'), False) 113 self.assertEqual(env('HELLO', 'true', var_type='boolean'), True) 114 self.assertEqual(env('HELLO', Decimal('3.14'), var_type='decimal'), Decimal('3.14')) 115 116''' 117Each CLI Test must be run outside of test suites in isolation 118since Click CLI Runner alters the global context 119''' 120def setup_CliRunner(test_func): 121 ''' 122 Decorator to initialize environment for CliRunner. 123 ''' 124 def wrapper(): 125 from click.testing import CliRunner 126 try: 127 from cli import envs as cli_envs 128 except ImportError: 129 from .cli import envs as cli_envs 130 131 try: 132 from cli import envs 133 except ImportError: 134 from .cli import envs 135 136 test_func() 137 138 return wrapper 139 140@mock.patch.object(sys, 'argv', ["list-envs"]) 141@setup_CliRunner 142def test_list_envs(): 143 os.environ.setdefault('DEBUG', 'True') 144 145 runner = CliRunner() 146 result = runner.invoke(envs, ['list-envs', '--settings-file', 'envs.test_settings', '--keep-result', 'True'], catch_exceptions=False) 147 148 output_expected = [{"default": None, "value": None, "var_type": "string", "key": "DATABASE_URL"},{"default": False, "value": "True", "var_type": "boolean", "key": "DEBUG"},{"default": [], "value": None, "var_type": "list", "key": "MIDDLEWARE"},{}] 149 150 with open('.envs_result', 'r') as f: 151 output_actual = json.load(f) 152 153 exit_code_expected = 0 154 exit_code_actual = result.exit_code 155 156 157 assert exit_code_actual == exit_code_expected 158 assert output_actual == output_expected 159 160 161 162 163 164if __name__ == '__main__': 165 unittest.main() 166 167