| import logging |
| import os |
| import sys |
| from datetime import datetime |
| from ankigen.logging import setup_logger |
|
|
|
|
| def test_setup_logger_returns_logger(): |
| """1) setup_logger returns a logging.Logger""" |
| logger = setup_logger("test_returns_logger") |
| assert isinstance(logger, logging.Logger) |
| assert logger.name == "test_returns_logger" |
|
|
|
|
| def test_setup_logger_handlers(tmp_path, monkeypatch): |
| """2) Logger has exactly 2 handlers (StreamHandler + FileHandler)""" |
| |
| monkeypatch.setattr( |
| "ankigen.logging.os.path.expanduser", lambda x: str(tmp_path) if x == "~" else x |
| ) |
|
|
| logger = setup_logger("test_handlers") |
|
|
| |
| assert len(logger.handlers) == 2 |
|
|
| handler_types = [type(h) for h in logger.handlers] |
| |
| assert any( |
| issubclass(t, logging.StreamHandler) and not issubclass(t, logging.FileHandler) |
| for t in handler_types |
| ) |
| |
| assert any(issubclass(t, logging.FileHandler) for t in handler_types) |
|
|
| |
| console_handler = next( |
| h |
| for h in logger.handlers |
| if isinstance(h, logging.StreamHandler) |
| and not isinstance(h, logging.FileHandler) |
| ) |
| assert console_handler.stream == sys.stdout |
|
|
|
|
| def test_file_handler_path_pattern(tmp_path, monkeypatch): |
| """3) File handler writes to the correct path pattern""" |
| monkeypatch.setattr( |
| "ankigen.logging.os.path.expanduser", lambda x: str(tmp_path) if x == "~" else x |
| ) |
|
|
| name = "test_path" |
| logger = setup_logger(name) |
|
|
| file_handler = next( |
| h for h in logger.handlers if isinstance(h, logging.FileHandler) |
| ) |
| log_file_path = file_handler.baseFilename |
|
|
| timestamp = datetime.now().strftime("%Y%m%d") |
| |
| expected_path = tmp_path / ".ankigen" / "logs" / f"{name}_{timestamp}.log" |
|
|
| assert os.path.abspath(log_file_path) == os.path.abspath(str(expected_path)) |
| |
| assert os.path.exists(os.path.dirname(log_file_path)) |
|
|
|
|
| def test_setup_logger_clears_old_handlers(tmp_path, monkeypatch): |
| """4) Calling setup_logger twice with same name clears old handlers (no duplicates)""" |
| monkeypatch.setattr( |
| "ankigen.logging.os.path.expanduser", lambda x: str(tmp_path) if x == "~" else x |
| ) |
|
|
| name = "test_clear_handlers" |
| logger = setup_logger(name) |
| assert len(logger.handlers) == 2 |
| initial_handlers = list(logger.handlers) |
|
|
| |
| logger2 = setup_logger(name) |
| assert logger is logger2 |
| assert len(logger2.handlers) == 2 |
|
|
| |
| for handler in initial_handlers: |
| assert handler not in logger2.handlers |
|
|
|
|
| def test_custom_log_level_respected(): |
| """5) Custom log_level is respected""" |
| name_debug = "test_log_level_debug" |
| logger_debug = setup_logger(name_debug, log_level=logging.DEBUG) |
| assert logger_debug.level == logging.DEBUG |
|
|
| name_info = "test_log_level_info" |
| logger_info = setup_logger(name_info, log_level=logging.INFO) |
| assert logger_info.level == logging.INFO |
|
|
|
|
| def test_custom_name_creates_distinct_logger(): |
| """6) Custom name creates a distinct logger""" |
| logger1 = setup_logger("logger1") |
| logger2 = setup_logger("logger2") |
| assert logger1.name == "logger1" |
| assert logger2.name == "logger2" |
| assert logger1 is not logger2 |
|
|