From 7323f49e7c308a6da1a068df39a5c9a36e69181e Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Thu, 28 May 2026 06:45:21 +0530 Subject: [PATCH 1/4] test: add unit tests for services/utils/logging_config.py (#40) --- tests/unit/test_logging_config.py | 145 ++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/unit/test_logging_config.py diff --git a/tests/unit/test_logging_config.py b/tests/unit/test_logging_config.py new file mode 100644 index 0000000..803f469 --- /dev/null +++ b/tests/unit/test_logging_config.py @@ -0,0 +1,145 @@ +""" +Unit tests for the logging configuration utility module. +""" +import logging +import os +import pytest +from unittest.mock import patch +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent.parent.parent / "services" / "utils")) + +from logging_config import setup_logging + + +class TestSetupLogging: + """Tests for the setup_logging function.""" + + def test_returns_logger_instance(self): + """Test that setup_logging returns a logging.Logger instance.""" + logger = setup_logging("test_logger") + assert isinstance(logger, logging.Logger) + + def test_logger_has_correct_name(self): + """Test that the logger is created with the correct name.""" + logger = setup_logging("my_service") + assert logger.name == "my_service" + + def test_default_log_level_is_info(self): + """Test that default log level is INFO when LOG_LEVEL env var is not set.""" + os.environ.pop("LOG_LEVEL", None) + logger = setup_logging("test_default_level") + assert logger.level == logging.INFO + + def test_log_level_from_environment(self): + """Test that log level is set from LOG_LEVEL environment variable.""" + with patch.dict(os.environ, {"LOG_LEVEL": "DEBUG"}): + logger = setup_logging("test_debug_level") + assert logger.level == logging.DEBUG + + def test_log_level_warning_from_environment(self): + """Test that WARNING log level is set correctly from environment.""" + with patch.dict(os.environ, {"LOG_LEVEL": "WARNING"}): + logger = setup_logging("test_warning_level") + assert logger.level == logging.WARNING + + def test_log_level_error_from_environment(self): + """Test that ERROR log level is set correctly from environment.""" + with patch.dict(os.environ, {"LOG_LEVEL": "ERROR"}): + logger = setup_logging("test_error_level") + assert logger.level == logging.ERROR + + def test_invalid_log_level_defaults_to_info(self): + """Test that invalid LOG_LEVEL defaults to INFO.""" + with patch.dict(os.environ, {"LOG_LEVEL": "INVALID_LEVEL"}): + logger = setup_logging("test_invalid_level") + assert logger.level == logging.INFO + + def test_logger_has_handlers(self): + """Test that the logger has handlers attached.""" + logger = setup_logging("test_handlers") + assert len(logger.handlers) > 0 + + def test_logger_has_console_handler(self): + """Test that a StreamHandler (console) is attached to the logger.""" + logger = setup_logging("test_console_handler") + handler_types = [type(h) for h in logger.handlers] + assert logging.StreamHandler in handler_types + + def test_logger_has_file_handler(self): + """Test that a RotatingFileHandler is attached to the logger.""" + from logging.handlers import RotatingFileHandler + logger = setup_logging("test_file_handler") + handler_types = [type(h) for h in logger.handlers] + assert RotatingFileHandler in handler_types + + def test_logger_propagate_is_false(self): + """Test that logger propagation is disabled.""" + logger = setup_logging("test_propagate") + assert logger.propagate is False + + def test_same_logger_no_duplicate_handlers(self): + """Test that calling setup_logging twice does not duplicate handlers.""" + logger1 = setup_logging("test_same_logger") + handler_count = len(logger1.handlers) + logger2 = setup_logging("test_same_logger") + assert len(logger2.handlers) == handler_count + + def test_logs_directory_created(self): + """Test that the logs directory is created.""" + setup_logging("test_logs_dir") + assert os.path.exists("logs") + + def test_log_format_contains_required_fields(self): + """Test that log formatter contains timestamp, name, level, and message.""" + logger = setup_logging("test_format") + for handler in logger.handlers: + if handler.formatter: + fmt = handler.formatter._fmt + assert "%(asctime)s" in fmt + assert "%(name)s" in fmt + assert "%(levelname)s" in fmt + assert "%(message)s" in fmt + break + + +class TestSensitiveDataLogging: + """Tests to ensure sensitive data handling.""" + + def test_logger_name_not_sensitive(self): + """Test that logger name does not contain sensitive information.""" + logger = setup_logging("test_service") + assert "password" not in logger.name.lower() + assert "secret" not in logger.name.lower() + assert "token" not in logger.name.lower() + + def test_logger_functional_for_normal_messages(self): + """Test that logger works normally without raising exceptions.""" + logger = setup_logging("test_sensitive") + try: + logger.info("User logged in successfully") + logger.warning("Test warning") + logger.error("Test error") + except Exception as e: + pytest.fail(f"Logger raised an exception: {e}") + + +class TestLogLevelCaseInsensitive: + """Tests for case insensitivity of LOG_LEVEL env variable.""" + + def test_lowercase_log_level(self): + """Test that lowercase log level env var is handled correctly.""" + with patch.dict(os.environ, {"LOG_LEVEL": "debug"}): + logger = setup_logging("test_lowercase") + assert logger.level == logging.DEBUG + + def test_mixed_case_log_level(self): + """Test that mixed case log level env var is handled correctly.""" + with patch.dict(os.environ, {"LOG_LEVEL": "Warning"}): + logger = setup_logging("test_mixed_case") + assert logger.level == logging.WARNING + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) \ No newline at end of file From 73e4fefb8c46be14a13f553854ffd633b5250f43 Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Fri, 29 May 2026 07:02:40 +0530 Subject: [PATCH 2/4] fix: resolve indentation and environment isolation issues in tests --- tests/unit/test_logging_config.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/unit/test_logging_config.py b/tests/unit/test_logging_config.py index 803f469..23d5bfb 100644 --- a/tests/unit/test_logging_config.py +++ b/tests/unit/test_logging_config.py @@ -28,9 +28,10 @@ def test_logger_has_correct_name(self): def test_default_log_level_is_info(self): """Test that default log level is INFO when LOG_LEVEL env var is not set.""" - os.environ.pop("LOG_LEVEL", None) - logger = setup_logging("test_default_level") - assert logger.level == logging.INFO + with patch.dict(os.environ, {}, clear=False): + os.environ.pop("LOG_LEVEL", None) + logger = setup_logging("test_default_level") + assert logger.level == logging.INFO def test_log_level_from_environment(self): """Test that log level is set from LOG_LEVEL environment variable.""" @@ -94,6 +95,7 @@ def test_logs_directory_created(self): def test_log_format_contains_required_fields(self): """Test that log formatter contains timestamp, name, level, and message.""" logger = setup_logging("test_format") + formatter_found = False for handler in logger.handlers: if handler.formatter: fmt = handler.formatter._fmt @@ -101,7 +103,9 @@ def test_log_format_contains_required_fields(self): assert "%(name)s" in fmt assert "%(levelname)s" in fmt assert "%(message)s" in fmt + formatter_found = True break + assert formatter_found, "No formatter found on any handler" class TestSensitiveDataLogging: @@ -115,14 +119,14 @@ def test_logger_name_not_sensitive(self): assert "token" not in logger.name.lower() def test_logger_functional_for_normal_messages(self): - """Test that logger works normally without raising exceptions.""" - logger = setup_logging("test_sensitive") - try: - logger.info("User logged in successfully") - logger.warning("Test warning") - logger.error("Test error") - except Exception as e: - pytest.fail(f"Logger raised an exception: {e}") + """Test that logger works normally without raising exceptions.""" + logger = setup_logging("test_sensitive") + try: + logger.info("User logged in successfully") + logger.warning("Test warning") + logger.error("Test error") + except Exception as e: + pytest.fail(f"Logger raised an exception: {e}") class TestLogLevelCaseInsensitive: From 749c2cc7efa01896b1e4744cf0562d4d7622e74a Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Fri, 29 May 2026 07:07:11 +0530 Subject: [PATCH 3/4] fix: improve test_logger_name_not_sensitive to document actual behavior --- tests/unit/test_logging_config.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/unit/test_logging_config.py b/tests/unit/test_logging_config.py index 23d5bfb..7ec1033 100644 --- a/tests/unit/test_logging_config.py +++ b/tests/unit/test_logging_config.py @@ -112,11 +112,12 @@ class TestSensitiveDataLogging: """Tests to ensure sensitive data handling.""" def test_logger_name_not_sensitive(self): - """Test that logger name does not contain sensitive information.""" - logger = setup_logging("test_service") - assert "password" not in logger.name.lower() - assert "secret" not in logger.name.lower() - assert "token" not in logger.name.lower() + """Test that setup_logging accepts safe logger names without modification.""" + safe_name = "test_service" + logger = setup_logging(safe_name) + assert logger.name == safe_name + # Document: callers must not pass sensitive data as logger names + # as setup_logging accepts the name verbatim without sanitization def test_logger_functional_for_normal_messages(self): """Test that logger works normally without raising exceptions.""" From c07d203298890dd90157b8d2def0a263f693ef44 Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Fri, 29 May 2026 07:53:25 +0530 Subject: [PATCH 4/4] fix: remove redundant try/except in test_logger_functional_for_normal_messages --- tests/unit/test_logging_config.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_logging_config.py b/tests/unit/test_logging_config.py index 7ec1033..b7a2556 100644 --- a/tests/unit/test_logging_config.py +++ b/tests/unit/test_logging_config.py @@ -122,12 +122,9 @@ def test_logger_name_not_sensitive(self): def test_logger_functional_for_normal_messages(self): """Test that logger works normally without raising exceptions.""" logger = setup_logging("test_sensitive") - try: - logger.info("User logged in successfully") - logger.warning("Test warning") - logger.error("Test error") - except Exception as e: - pytest.fail(f"Logger raised an exception: {e}") + logger.info("User logged in successfully") + logger.warning("Test warning") + logger.error("Test error") class TestLogLevelCaseInsensitive: