Mercurial > p > roundup > code
comparison test/test_config.py @ 8447:d06be9346c68
bug, test: fix tests for trace_id; readd import logging.config
Made save_restore_logging a test level fixture. It was a class level
which worked fine until I started using caplog for tests in the same
class. Due to loading config from dict, the roundup channel was set to
not propagate which broke the new formatting test used for trace_id.
Forgot to update some tests due to change in default format adding
%(trace_id).
Also re-added logging.config import which broke loading logging config
files in configuration.py.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Wed, 17 Sep 2025 00:45:04 -0400 |
| parents | 14c7c07b32d8 |
| children | 401c6f0be6c5 |
comparison
equal
deleted
inserted
replaced
| 8446:14c7c07b32d8 | 8447:d06be9346c68 |
|---|---|
| 420 | 420 |
| 421 @pytest.fixture(autouse=True) | 421 @pytest.fixture(autouse=True) |
| 422 def inject_fixtures(self, caplog): | 422 def inject_fixtures(self, caplog): |
| 423 self._caplog = caplog | 423 self._caplog = caplog |
| 424 | 424 |
| 425 @pytest.fixture(scope="class") | 425 @pytest.fixture(autouse=True) |
| 426 def save_restore_logging(self): | 426 def save_restore_logging(self): |
| 427 """Save logger state and try to restore it after all tests in | 427 """Save logger state and try to restore it after all tests in |
| 428 this class have finished. | 428 this class have finished. |
| 429 | 429 |
| 430 The primary test is testDictLoggerConfigViaJson which | 430 The primary test is testDictLoggerConfigViaJson which |
| 459 if name.startswith("roundup")] | 459 if name.startswith("roundup")] |
| 460 | 460 |
| 461 # cribbed from configuration.py:init_loggers | 461 # cribbed from configuration.py:init_loggers |
| 462 hdlr = logging.StreamHandler(sys.stdout) | 462 hdlr = logging.StreamHandler(sys.stdout) |
| 463 formatter = logging.Formatter( | 463 formatter = logging.Formatter( |
| 464 '%(asctime)s %(levelname)s %(message)s') | 464 '%(asctime)s %(trace_id)s %(levelname)s %(message)s') |
| 465 hdlr.setFormatter(formatter) | 465 hdlr.setFormatter(formatter) |
| 466 | 466 |
| 467 for logger in roundup_loggers: | 467 for logger in roundup_loggers: |
| 468 # no logging API to remove all existing handlers!?! | 468 # no logging API to remove all existing handlers!?! |
| 469 for h in logger.handlers: | 469 for h in logger.handlers: |
| 1017 """Depends on using default logging format with %(trace_id)""" | 1017 """Depends on using default logging format with %(trace_id)""" |
| 1018 | 1018 |
| 1019 def find_file_occurances(string): | 1019 def find_file_occurances(string): |
| 1020 return len(re.findall(r'\bFile\b', string)) | 1020 return len(re.findall(r'\bFile\b', string)) |
| 1021 | 1021 |
| 1022 config = configuration.CoreConfig() | 1022 config = configuration.CoreConfig(settings={"LOGGING_LEVEL": "DEBUG"}) |
| 1023 | |
| 1024 config.LOGGING_LEVEL = "DEBUG" | |
| 1025 config.init_logging() | |
| 1026 | |
| 1027 | 1023 |
| 1028 # format the record and verify the logformat/trace_id. | 1024 # format the record and verify the logformat/trace_id. |
| 1029 config._logging_test(None, msg="message") | 1025 config._logging_test(None, msg="message") |
| 1030 tuple = self._caplog.record_tuples[0] | 1026 tuple = self._caplog.record_tuples[0] |
| 1031 self.assertEqual(tuple[1], 20) | 1027 self.assertEqual(tuple[1], 20) |
| 1034 hdlr = logger.handlers[0] | 1030 hdlr = logger.handlers[0] |
| 1035 log = hdlr.format(self._caplog.records[0]) | 1031 log = hdlr.format(self._caplog.records[0]) |
| 1036 # verify that %(trace_id) was set and substituted | 1032 # verify that %(trace_id) was set and substituted |
| 1037 # Note: trace_id is not initialized in this test case | 1033 # Note: trace_id is not initialized in this test case |
| 1038 log_parts = log.split() | 1034 log_parts = log.split() |
| 1039 self.assertRegex(log_parts[2], r'^[A-Za-z0-9]{22}') | 1035 # testing len(shorten_int_uuid(uuid.uuid4().int)) |
| 1036 # for 20000 tests gives range [19,22] | |
| 1037 self.assertRegex(log_parts[2], r'^[A-Za-z0-9]{19,22}') | |
| 1040 self._caplog.clear() | 1038 self._caplog.clear() |
| 1041 | 1039 |
| 1042 # the rest check various values of sinfo and msg formating. | 1040 # the rest check various values of sinfo and msg formating. |
| 1043 | 1041 |
| 1044 # sinfo = 1 - one line of stack starting with log call | 1042 # sinfo = 1 - one line of stack starting with log call |
| 1248 def testLoggerFormat(self): | 1246 def testLoggerFormat(self): |
| 1249 config = configuration.CoreConfig() | 1247 config = configuration.CoreConfig() |
| 1250 | 1248 |
| 1251 # verify config is initalized to defaults | 1249 # verify config is initalized to defaults |
| 1252 self.assertEqual(config['LOGGING_FORMAT'], | 1250 self.assertEqual(config['LOGGING_FORMAT'], |
| 1253 '%(asctime)s %(levelname)s %(message)s') | 1251 '%(asctime)s %(trace_id)s %(levelname)s %(message)s') |
| 1254 | 1252 |
| 1255 # load config | 1253 # load config |
| 1256 config.load(self.dirname) | 1254 config.load(self.dirname) |
| 1257 self.assertEqual(config['LOGGING_FORMAT'], | 1255 self.assertEqual(config['LOGGING_FORMAT'], |
| 1258 '%(asctime)s %(levelname)s %(message)s') | 1256 '%(asctime)s %(trace_id)s %(levelname)s %(message)s') |
| 1259 | 1257 |
| 1260 # break config using an incomplete format specifier (no trailing 's') | 1258 # break config using an incomplete format specifier (no trailing 's') |
| 1261 self.munge_configini(mods=[ ("format = ", "%%(asctime)s %%(levelname) %%(message)s") ], section="[logging]") | 1259 self.munge_configini(mods=[ ("format = ", "%%(asctime)s %%(trace_id)s %%(levelname) %%(message)s") ], section="[logging]") |
| 1262 | 1260 |
| 1263 # load config | 1261 # load config |
| 1264 with self.assertRaises(configuration.OptionValueError) as cm: | 1262 with self.assertRaises(configuration.OptionValueError) as cm: |
| 1265 config.load(self.dirname) | 1263 config.load(self.dirname) |
| 1266 | 1264 |
| 1267 self.assertIn('Unrecognized use of %(...) in: %(levelname)', | 1265 self.assertIn('Unrecognized use of %(...) in: %(levelname)', |
| 1268 cm.exception.args[2]) | 1266 cm.exception.args[2]) |
| 1269 | 1267 |
| 1270 # break config by not dubling % sign to quote it from configparser | 1268 # break config by not doubling % sign to quote it from configparser |
| 1271 self.munge_configini(mods=[ ("format = ", "%(asctime)s %%(levelname) %%(message)s") ], section="[logging]") | 1269 self.munge_configini(mods=[ ("format = ", "%(asctime)s %%(trace_id)s %%(levelname) %%(message)s") ], section="[logging]") |
| 1272 | 1270 |
| 1273 with self.assertRaises( | 1271 with self.assertRaises( |
| 1274 configuration.ParsingOptionError) as cm: | 1272 configuration.ParsingOptionError) as cm: |
| 1275 config.load(self.dirname) | 1273 config.load(self.dirname) |
| 1276 | 1274 |
| 1277 self.assertEqual(cm.exception.args[0], | 1275 self.assertEqual(cm.exception.args[0], |
| 1278 "Error in _test_instance/config.ini with section " | 1276 "Error in _test_instance/config.ini with section " |
| 1279 "[logging] at option format: Bad value substitution: " | 1277 "[logging] at option format: Bad value substitution: " |
| 1280 "option 'format' in section 'logging' contains an " | 1278 "option 'format' in section 'logging' contains an " |
| 1281 "interpolation key 'asctime' which is not a valid " | 1279 "interpolation key 'asctime' which is not a valid " |
| 1282 "option name. Raw value: '%(asctime)s %%(levelname) " | 1280 "option name. Raw value: '%(asctime)s %%(trace_id)s " |
| 1283 "%%(message)s'") | 1281 "%%(levelname) %%(message)s'") |
| 1284 | 1282 |
| 1285 def testDictLoggerConfigViaJson(self): | 1283 def testDictLoggerConfigViaJson(self): |
| 1286 | 1284 |
| 1287 # good base test case | 1285 # good base test case |
| 1288 config1 = dedent(""" | 1286 config1 = dedent(""" |
