| #!/usr/bin/env python3 |
| # |
| # Copyright 2018 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| import logging |
| import unittest |
| |
| import mock |
| from acts.event.event import TestCaseBeginEvent |
| from acts.event.event import TestClassBeginEvent |
| |
| from acts.libs.logging import log_stream |
| from acts.libs.logging.log_stream import AlsoToLogHandler |
| from acts.libs.logging.log_stream import _LogStream |
| from acts.libs.logging.log_stream import InvalidStyleSetError |
| from acts.libs.logging.log_stream import LogStyles |
| |
| |
| class TestClass(object): |
| """Dummy class for TestEvents""" |
| def __init__(self): |
| self.test_name = self.test_case.__name__ |
| |
| def test_case(self): |
| """Dummy test case for test events.""" |
| |
| |
| class LogStreamTest(unittest.TestCase): |
| """Tests the _LogStream class in acts.libs.logging.log_stream.""" |
| |
| @staticmethod |
| def patch(imported_name, *args, **kwargs): |
| return mock.patch('acts.libs.logging.log_stream.%s' % imported_name, |
| *args, **kwargs) |
| |
| @classmethod |
| def setUpClass(cls): |
| # logging.log_path only exists if logger._setup_test_logger is called. |
| # Here we set it to a value that is likely to not exist so file IO is |
| # not executed (an error is raised instead of creating the file). |
| logging.log_path = '/f/a/i/l/p/a/t/h' |
| |
| def setUp(self): |
| log_stream._log_streams = dict() |
| |
| # __init__ |
| |
| @mock.patch('os.makedirs') |
| def test_init_adds_null_handler(self, *_): |
| """Tests that a NullHandler is added to the logger upon initialization. |
| This ensures that no log output is generated when a test class is not |
| running. |
| """ |
| debug_monolith_log = LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG |
| with self.patch('FileHandler'): |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=debug_monolith_log) |
| |
| self.assertTrue(isinstance(log.handlers[0], logging.NullHandler)) |
| |
| # __validate_style |
| |
| @mock.patch('os.makedirs') |
| def test_validate_styles_raises_when_same_location_set_multiple_times( |
| self, *_): |
| """Tests that a style is invalid if it sets the same handler twice. |
| |
| If the error is NOT raised, then a LogStream can create a Logger that |
| has multiple LogHandlers trying to write to the same file. |
| """ |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger( |
| self._testMethodName, |
| log_styles=[LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG, |
| LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) |
| self.assertTrue( |
| 'has been set multiple' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| @mock.patch('os.makedirs') |
| def test_validate_styles_raises_when_multiple_file_outputs_set( |
| self, *_): |
| """Tests that a style is invalid if more than one of MONOLITH_LOG, |
| TESTCLASS_LOG, and TESTCASE_LOG is set for the same log level. |
| |
| If the error is NOT raised, then a LogStream can create a Logger that |
| has multiple LogHandlers trying to write to the same file. |
| """ |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger( |
| self._testMethodName, |
| log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, |
| LogStyles.LOG_DEBUG | LogStyles.TESTCLASS_LOG]) |
| self.assertTrue( |
| 'More than one of' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger( |
| self._testMethodName, |
| log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, |
| LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) |
| self.assertTrue( |
| 'More than one of' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger( |
| self._testMethodName, |
| log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, |
| LogStyles.LOG_DEBUG | LogStyles.TESTCLASS_LOG, |
| LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) |
| self.assertTrue( |
| 'More than one of' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| @mock.patch('os.makedirs') |
| def test_validate_styles_raises_when_no_level_exists(self, *_): |
| """Tests that a style is invalid if it does not contain a log level. |
| |
| If the style does not contain a log level, then there is no way to |
| pass the information coming from the logger to the correct file. |
| """ |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger(self._testMethodName, |
| log_styles=[LogStyles.MONOLITH_LOG]) |
| |
| self.assertTrue( |
| 'log level' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| @mock.patch('os.makedirs') |
| def test_validate_styles_raises_when_no_location_exists(self, *_): |
| """Tests that a style is invalid if it does not contain a log level. |
| |
| If the style does not contain a log level, then there is no way to |
| pass the information coming from the logger to the correct file. |
| """ |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger(self._testMethodName, |
| log_styles=[LogStyles.LOG_INFO]) |
| |
| self.assertTrue( |
| 'log location' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| @mock.patch('os.makedirs') |
| def test_validate_styles_raises_when_rotate_logs_no_file_handler(self, *_): |
| """Tests that a LogStyle cannot set ROTATE_LOGS without *_LOG flag. |
| |
| If the LogStyle contains ROTATE_LOGS, it must be associated with a log |
| that is rotatable. TO_ACTS_LOG and TO_STDOUT are not rotatable logs, |
| since those are both controlled by another object/process. The user |
| must specify MONOLITHIC_LOG or TESTCASE_LOG. |
| """ |
| with self.assertRaises(InvalidStyleSetError) as catch: |
| log_stream.create_logger( |
| self._testMethodName, |
| # Added LOG_DEBUG here to prevent the no_level_exists raise from |
| # occurring. |
| log_styles=[LogStyles.LOG_DEBUG + LogStyles.ROTATE_LOGS]) |
| |
| self.assertTrue( |
| 'log type' in catch.exception.args[0], |
| msg='__validate_styles did not raise the expected error message') |
| |
| # __handle_style |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_create_test_case_descriptors(self, *_): |
| """Tests that handle_style creates the correct test case descriptors |
| and the outer-level test class descriptors. |
| |
| The above descriptors are only created on TESTCASE_LOG logstyles. |
| """ |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_stream = log_stream._log_streams[self._testMethodName] |
| case_descriptors = created_stream._test_case_handler_descriptors |
| class_descriptors = created_stream._test_class_only_handler_descriptors |
| |
| self.assertEqual(len(case_descriptors), 1, |
| 'There should be exactly 1 testcase handler' |
| 'descriptor created.') |
| self.assertEqual(len(class_descriptors), 1, |
| 'There should be exactly 1 test class only handler' |
| 'descriptor created.') |
| self.assertEqual(case_descriptors[0]._level, logging.INFO) |
| self.assertEqual(class_descriptors[0]._level, logging.INFO) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_does_not_create_test_case_descriptors(self, *_): |
| """Tests that handle_style does not create test case and test class |
| only descriptors without LogStyle.TESTCASE_LOG. |
| """ |
| info_monolith_log = (LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG) |
| |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_monolith_log) |
| |
| created_stream = log_stream._log_streams[self._testMethodName] |
| case_descriptors = created_stream._test_case_handler_descriptors |
| class_descriptors = created_stream._test_class_only_handler_descriptors |
| |
| self.assertEqual(len(case_descriptors), 0, |
| 'Testcase handlers should not be created without a ' |
| 'TESTCASE_LOG LogStyle.') |
| self.assertEqual(len(class_descriptors), 0, |
| 'Test class only handlers should not be created ' |
| 'without a TESTCASE_LOG LogStyle.') |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_create_test_class_descriptors(self, *_): |
| """Tests that handle_style creates the correct test class descriptors. |
| |
| The above descriptors are only created on TESTCLASS_LOG logstyles. |
| """ |
| info_testclass_log = LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG |
| |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testclass_log) |
| |
| created_stream = log_stream._log_streams[self._testMethodName] |
| class_descriptors = created_stream._test_class_handler_descriptors |
| |
| self.assertEqual(len(class_descriptors), 1, |
| 'There should be exactly 1 test class handler' |
| 'descriptor created.') |
| self.assertEqual(class_descriptors[0]._level, logging.INFO) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_does_not_create_test_class_descriptors(self, *_): |
| """Tests that handle_style does not create test class descriptors |
| without LogStyle.TESTCLASS_LOG. |
| """ |
| info_monolith_log = (LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG) |
| |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_monolith_log) |
| |
| created_stream = log_stream._log_streams[self._testMethodName] |
| class_descriptors = created_stream._test_class_handler_descriptors |
| |
| self.assertEqual(len(class_descriptors), 0, |
| 'Test class handlers should not be created without a ' |
| 'TESTCLASS_LOG LogStyle.') |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_to_acts_log_creates_handler(self, *_): |
| """Tests that using the flag TO_ACTS_LOG creates an AlsoToLogHandler.""" |
| info_acts_log = LogStyles.LOG_INFO + LogStyles.TO_ACTS_LOG |
| |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=info_acts_log) |
| |
| self.assertTrue(isinstance(log.handlers[1], AlsoToLogHandler)) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_to_acts_log_creates_handler_is_lowest_level(self, *_): |
| """Tests that using the flag TO_ACTS_LOG creates an AlsoToLogHandler |
| that is set to the lowest LogStyles level.""" |
| info_acts_log = (LogStyles.LOG_DEBUG + LogStyles.LOG_INFO + |
| LogStyles.TO_ACTS_LOG) |
| |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=info_acts_log) |
| |
| self.assertTrue(isinstance(log.handlers[1], AlsoToLogHandler)) |
| self.assertEqual(log.handlers[1].level, logging.DEBUG) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_to_stdout_creates_stream_handler(self, *_): |
| """Tests that using the flag TO_STDOUT creates a StreamHandler.""" |
| info_acts_log = LogStyles.LOG_INFO + LogStyles.TO_STDOUT |
| |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=info_acts_log) |
| |
| self.assertTrue(isinstance(log.handlers[1], logging.StreamHandler)) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_creates_file_handler(self, *_): |
| """Tests handle_style creates a FileHandler for the MONOLITH_LOG.""" |
| info_acts_log = LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG |
| |
| expected = mock.MagicMock() |
| with self.patch('FileHandler', return_value=expected): |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=info_acts_log) |
| |
| self.assertEqual(log.handlers[1], expected) |
| |
| @mock.patch('os.makedirs') |
| def test_handle_style_creates_rotating_file_handler(self, *_): |
| """Tests handle_style creates a FileHandler for the ROTATE_LOGS.""" |
| info_acts_log = (LogStyles.LOG_INFO + LogStyles.ROTATE_LOGS + |
| LogStyles.MONOLITH_LOG) |
| |
| expected = mock.MagicMock() |
| with self.patch('RotatingFileHandler', return_value=expected): |
| log = log_stream.create_logger(self._testMethodName, |
| log_styles=info_acts_log) |
| |
| self.assertEqual(log.handlers[1], expected) |
| |
| # __create_rotating_file_handler |
| |
| @mock.patch('os.makedirs') |
| def test_create_rotating_file_handler_does_what_it_says_it_does(self, *_): |
| """Tests that __create_rotating_file_handler does exactly that.""" |
| expected = mock.MagicMock() |
| |
| with self.patch('RotatingFileHandler', return_value=expected): |
| # Through name-mangling, this function is automatically renamed. See |
| # https://docs.python.org/3/tutorial/classes.html#private-variables |
| fh = _LogStream._LogStream__create_rotating_file_handler('') |
| |
| self.assertEqual(expected, fh, |
| 'The function did not return a RotatingFileHandler.') |
| |
| # __get_file_handler_creator |
| |
| @mock.patch('os.makedirs') |
| def test_get_file_handler_creator_returns_rotating_file_handler(self, *_): |
| """Tests the function returns a RotatingFileHandler when the log_style |
| has LogStyle.ROTATE_LOGS.""" |
| expected = mock.MagicMock() |
| |
| with self.patch('_LogStream._LogStream__create_rotating_file_handler', |
| return_value=expected): |
| # Through name-mangling, this function is automatically renamed. See |
| # https://docs.python.org/3/tutorial/classes.html#private-variables |
| fh_creator = _LogStream._LogStream__get_file_handler_creator( |
| LogStyles.ROTATE_LOGS) |
| |
| self.assertEqual(expected, fh_creator('/d/u/m/m/y/p/a/t/h'), |
| 'The function did not return a RotatingFileHandler.') |
| |
| @mock.patch('os.makedirs') |
| def test_get_file_handler_creator_returns_file_handler(self, *_): |
| """Tests the function returns a FileHandler when the log_style does NOT |
| have LogStyle.ROTATE_LOGS.""" |
| expected = mock.MagicMock() |
| |
| with self.patch('FileHandler', return_value=expected): |
| # Through name-mangling, this function is automatically renamed. See |
| # https://docs.python.org/3/tutorial/classes.html#private-variables |
| handler = _LogStream._LogStream__get_file_handler_creator( |
| LogStyles.NONE)() |
| |
| self.assertTrue(isinstance(handler, mock.Mock)) |
| |
| # __get_lowest_log_level |
| |
| @mock.patch('os.makedirs') |
| def test_get_lowest_level_gets_lowest_level(self, *_): |
| """Tests __get_lowest_level returns the lowest LogStyle level given.""" |
| level = _LogStream._LogStream__get_lowest_log_level( |
| LogStyles.ALL_LEVELS) |
| self.assertEqual(level, LogStyles.LOG_DEBUG) |
| |
| # __remove_handler |
| |
| @mock.patch('os.makedirs') |
| def test_remove_handler_removes_a_handler(self, *_): |
| dummy_obj = mock.Mock() |
| dummy_obj.logger = mock.Mock() |
| handler = mock.Mock() |
| _LogStream._LogStream__remove_handler(dummy_obj, handler) |
| |
| self.assertTrue(dummy_obj.logger.removeHandler.called) |
| self.assertTrue(handler.close.called) |
| |
| # __create_handlers_from_descriptors |
| |
| @mock.patch('os.makedirs') |
| def test_create_handlers_from_descriptors(self, *_): |
| """Tests that the handlers generated from the descriptors are added |
| to the associated logger and the given handlers list.""" |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| with self.patch('FileHandler', |
| side_effect=[mock.MagicMock(name='handler1'), |
| mock.MagicMock(name='handler2')]): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| descriptors = created_log_stream._test_case_handler_descriptors |
| testcase_handlers = [] |
| num_logger_handlers = len(created_log_stream.logger.handlers) |
| created_log_stream._LogStream__create_handlers_from_descriptors( |
| descriptors, testcase_handlers, |
| TestCaseBeginEvent(TestClass(), TestClass.test_case)) |
| |
| self.assertGreater(len(created_log_stream.logger.handlers), |
| num_logger_handlers, |
| 'No handlers added to the logger') |
| self.assertGreater(len(testcase_handlers), 0, |
| 'Handler list not populated.') |
| |
| # on_test_case_end |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_case_end_removes_all_handlers(self, *_): |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_case_end('') |
| |
| self.assertEqual(len(created_log_stream._test_case_log_handlers), 0, |
| 'The test case log handlers were not cleared.') |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_case_end_enables_class_level_handlers(self, *_): |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| with self.patch('FileHandler', |
| side_effect=[mock.MagicMock(name='run_handler'), |
| mock.MagicMock(name='class_handler'), |
| mock.MagicMock(name='case_handler')]): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_class_begin(TestClassBeginEvent(TestClass())) |
| created_log_stream.on_test_case_begin( |
| TestCaseBeginEvent(TestClass(), TestClass.test_case)) |
| created_log_stream.on_test_case_end('') |
| |
| self.assertGreater( |
| len(created_log_stream._test_class_only_log_handlers), 0, |
| 'The test class only log handlers list is empty.') |
| for handler in created_log_stream._test_class_only_log_handlers: |
| self.assertIn(handler, created_log_stream.logger.handlers, |
| 'A class level handler is not enabled on test case ' |
| 'end.') |
| |
| # on_test_case_begin |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_case_begin_creates_new_handlers(self, *_): |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_case_begin( |
| TestCaseBeginEvent(TestClass(), TestClass.test_case)) |
| |
| self.assertEqual(len(created_log_stream._test_case_log_handlers), 1) |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_case_begin_disables_class_level_handlers(self, *_): |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.TESTCASE_LOG |
| with self.patch('FileHandler', |
| side_effect=[mock.MagicMock(name='run_handler'), |
| mock.MagicMock(name='class_handler'), |
| mock.MagicMock(name='case_handler')]): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| |
| created_log_stream.on_test_class_begin(TestClassBeginEvent(TestClass())) |
| created_log_stream.on_test_case_begin( |
| TestCaseBeginEvent(TestClass(), TestClass.test_case)) |
| |
| self.assertGreater( |
| len(created_log_stream._test_class_only_log_handlers), 0, |
| 'The test class only log handlers list is empty.') |
| for handler in created_log_stream._test_class_only_log_handlers: |
| self.assertNotIn(handler, created_log_stream.logger.handlers, |
| 'A class level handler is not disabled on ' |
| 'test case begin.') |
| |
| # on_test_class_end |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_class_end_removes_all_handlers(self, *_): |
| testclass_log = [ |
| LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG, |
| LogStyles.LOG_DEBUG + LogStyles.TESTCASE_LOG] |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=testclass_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_class_end('') |
| |
| self.assertEqual(len(created_log_stream._test_class_log_handlers), 0, |
| 'The test class log handlers were not cleared.') |
| self.assertEqual(len(created_log_stream._test_class_only_log_handlers), |
| 0, 'The test class only log handlers were not ' |
| 'cleared.') |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_class_end_enables_run_level_handlers(self, *_): |
| info_testclass_log = LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG |
| with self.patch('FileHandler', |
| side_effect=[mock.MagicMock(name='run_handler'), |
| mock.MagicMock(name='class_handler')]): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testclass_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_class_begin(TestClassBeginEvent(TestClass())) |
| created_log_stream.on_test_class_end('') |
| |
| self.assertGreater( |
| len(created_log_stream._test_run_only_log_handlers), 0, |
| 'The test run only log handlers list is empty.') |
| for handler in created_log_stream._test_run_only_log_handlers: |
| self.assertIn(handler, created_log_stream.logger.handlers, |
| 'A run level handler is not enabled on test class ' |
| 'end.') |
| |
| # on_test_class_begin |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_class_begin_creates_new_handlers(self, *_): |
| testclass_log = [ |
| LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG, |
| LogStyles.LOG_DEBUG + LogStyles.TESTCASE_LOG] |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=testclass_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.on_test_class_begin( |
| TestClassBeginEvent(TestClass())) |
| |
| self.assertEqual(len(created_log_stream._test_class_log_handlers), 1) |
| self.assertEqual(len(created_log_stream._test_class_only_log_handlers), |
| 1) |
| |
| @mock.patch('os.makedirs') |
| def test_on_test_class_begin_disables_run_level_handlers(self, *_): |
| info_testclass_log = LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG |
| with self.patch('FileHandler', |
| side_effect=[mock.MagicMock(name='run_handler'), |
| mock.MagicMock(name='class_handler')]): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testclass_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| |
| created_log_stream.on_test_class_begin(TestClassBeginEvent(TestClass())) |
| |
| self.assertGreater( |
| len(created_log_stream._test_run_only_log_handlers), 0, |
| 'The test run only log handlers list is empty.') |
| for handler in created_log_stream._test_run_only_log_handlers: |
| self.assertNotIn(handler, created_log_stream.logger.handlers, |
| 'A run level handler is not disabled on test ' |
| 'class begin.') |
| |
| # cleanup |
| |
| @mock.patch('os.makedirs') |
| def test_cleanup_removes_all_handlers(self, *_): |
| """ Tests that cleanup removes all handlers in the logger, except |
| the NullHandler. |
| """ |
| info_testcase_log = LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG |
| with self.patch('FileHandler'): |
| log_stream.create_logger(self._testMethodName, |
| log_styles=info_testcase_log) |
| |
| created_log_stream = log_stream._log_streams[self._testMethodName] |
| created_log_stream.cleanup() |
| |
| self.assertEqual(len(created_log_stream.logger.handlers), 1) |
| |
| |
| class LogStreamModuleTests(unittest.TestCase): |
| @classmethod |
| def setUpClass(cls): |
| # logging.log_path only exists if logger._setup_test_logger is called. |
| # Here we set it to a value that is likely to not exist so file IO is |
| # not executed (an error is raised instead of creating the file). |
| logging.log_path = '/f/a/i/l/p/a/t/h' |
| |
| def setUp(self): |
| log_stream._log_streams = {} |
| |
| # _on_test_class_begin |
| |
| @staticmethod |
| def create_test_class_event(): |
| return TestClassBeginEvent(TestClass()) |
| |
| def test_on_test_class_begin_delegates_calls_to_log_streams(self): |
| """Tests on_test_class_begin calls on_test_class_begin on each log_stream. |
| """ |
| log_stream._log_streams = { |
| 'a': mock.Mock(), |
| 'b': mock.Mock() |
| } |
| |
| log_stream._on_test_class_begin(self.create_test_class_event()) |
| |
| self.assertTrue(log_stream._log_streams['a'].on_test_class_begin.called) |
| self.assertTrue(log_stream._log_streams['b'].on_test_class_begin.called) |
| |
| # _on_test_class_end |
| |
| def test_on_test_class_end_delegates_calls_to_log_streams(self): |
| """Tests on_test_class_end calls on_test_class_end on each log_stream. |
| """ |
| log_stream._log_streams = { |
| 'a': mock.Mock(), |
| 'b': mock.Mock() |
| } |
| |
| log_stream._on_test_class_end(self.create_test_class_event()) |
| |
| self.assertTrue(log_stream._log_streams['a'].on_test_class_end.called) |
| self.assertTrue(log_stream._log_streams['b'].on_test_class_end.called) |
| |
| # _on_test_case_begin |
| |
| @staticmethod |
| def create_test_case_event(): |
| return TestCaseBeginEvent(TestClass(), TestClass.test_case) |
| |
| def test_on_test_case_begin_delegates_calls_to_log_streams(self): |
| """Tests on_test_case_begin calls on_test_case_begin on each log_stream. |
| """ |
| log_stream._log_streams = { |
| 'a': mock.Mock(), |
| 'b': mock.Mock() |
| } |
| |
| log_stream._on_test_case_begin(self.create_test_case_event()) |
| |
| self.assertTrue(log_stream._log_streams['a'].on_test_case_begin.called) |
| self.assertTrue(log_stream._log_streams['b'].on_test_case_begin.called) |
| |
| # _on_test_case_end |
| |
| def test_on_test_case_end_delegates_calls_to_log_streams(self): |
| """Tests on_test_case_begin calls on_test_case_begin on each log_stream. |
| """ |
| log_stream._log_streams = { |
| 'a': mock.Mock(), |
| 'b': mock.Mock() |
| } |
| |
| log_stream._on_test_case_end(self.create_test_case_event()) |
| |
| self.assertTrue(log_stream._log_streams['a'].on_test_case_end.called) |
| self.assertTrue(log_stream._log_streams['b'].on_test_case_end.called) |
| |
| # _set_logger |
| |
| def test_set_logger_overwrites_previous_logger(self): |
| """Tests that calling set_logger overwrites the previous logger within |
| log_stream._log_streams. |
| """ |
| previous = mock.Mock() |
| log_stream._log_streams = { |
| 'a': previous |
| } |
| expected = mock.Mock() |
| expected.name = 'a' |
| log_stream._set_logger(expected) |
| |
| self.assertEqual(log_stream._log_streams['a'], expected) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |