feat(core): add core module with mixins, services, and background jobs
- Add Model Mixins: TimestampMixin, SoftDeleteMixin, AuditMixin, etc. - Add Base Services: BaseService, BulkOperationsMixin, QueryOptimizerMixin - Add Base ViewSets with bulk operations - Add BackgroundJob model for Celery task tracking - Add BaseAppCommand for management commands - Add permissions, pagination, filters, cache, logging - Migrate tests to factory_boy + faker - Add CHANGELOG.md - 297 tests passing
This commit is contained in:
163
tests/apps/core/test_logging.py
Normal file
163
tests/apps/core/test_logging.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""Tests for core logging utilities"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from io import StringIO
|
||||
|
||||
from apps.core.logging import (
|
||||
ContextLogger,
|
||||
JSONFormatter,
|
||||
get_json_logging_config,
|
||||
)
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class JSONFormatterTest(TestCase):
|
||||
"""Tests for JSONFormatter"""
|
||||
|
||||
def setUp(self):
|
||||
self.formatter = JSONFormatter()
|
||||
self.logger = logging.getLogger("test_json")
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
# Remove existing handlers
|
||||
self.logger.handlers = []
|
||||
|
||||
# Add handler with JSONFormatter
|
||||
self.stream = StringIO()
|
||||
handler = logging.StreamHandler(self.stream)
|
||||
handler.setFormatter(self.formatter)
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
def test_output_is_valid_json(self):
|
||||
"""Test that output is valid JSON"""
|
||||
self.logger.info("Test message")
|
||||
output = self.stream.getvalue()
|
||||
|
||||
# Should not raise
|
||||
parsed = json.loads(output)
|
||||
self.assertIsInstance(parsed, dict)
|
||||
|
||||
def test_contains_required_fields(self):
|
||||
"""Test that output contains required fields"""
|
||||
self.logger.info("Test message")
|
||||
output = self.stream.getvalue()
|
||||
parsed = json.loads(output)
|
||||
|
||||
self.assertIn("timestamp", parsed)
|
||||
self.assertIn("level", parsed)
|
||||
self.assertIn("logger", parsed)
|
||||
self.assertIn("message", parsed)
|
||||
|
||||
def test_level_is_correct(self):
|
||||
"""Test that log level is correct"""
|
||||
self.logger.warning("Warning message")
|
||||
output = self.stream.getvalue()
|
||||
parsed = json.loads(output)
|
||||
|
||||
self.assertEqual(parsed["level"], "WARNING")
|
||||
|
||||
def test_message_is_correct(self):
|
||||
"""Test that message is correct"""
|
||||
self.logger.info("My test message")
|
||||
output = self.stream.getvalue()
|
||||
parsed = json.loads(output)
|
||||
|
||||
self.assertEqual(parsed["message"], "My test message")
|
||||
|
||||
def test_extra_fields_included(self):
|
||||
"""Test that extra fields are included"""
|
||||
self.logger.info("Test message", extra={"user_id": 42, "action": "login"})
|
||||
output = self.stream.getvalue()
|
||||
parsed = json.loads(output)
|
||||
|
||||
self.assertIn("extra", parsed)
|
||||
self.assertEqual(parsed["extra"]["user_id"], 42)
|
||||
self.assertEqual(parsed["extra"]["action"], "login")
|
||||
|
||||
def test_exception_info_included(self):
|
||||
"""Test that exception info is included"""
|
||||
try:
|
||||
raise ValueError("Test error")
|
||||
except ValueError:
|
||||
self.logger.exception("An error occurred")
|
||||
|
||||
output = self.stream.getvalue()
|
||||
parsed = json.loads(output)
|
||||
|
||||
self.assertIn("exception", parsed)
|
||||
self.assertEqual(parsed["exception"]["type"], "ValueError")
|
||||
self.assertIn("Test error", parsed["exception"]["message"])
|
||||
|
||||
|
||||
class ContextLoggerTest(TestCase):
|
||||
"""Tests for ContextLogger"""
|
||||
|
||||
def setUp(self):
|
||||
self.context_logger = ContextLogger("test_context")
|
||||
|
||||
def test_set_context(self):
|
||||
"""Test context is stored"""
|
||||
self.context_logger.set_context(user_id=42, action="test")
|
||||
|
||||
self.assertEqual(self.context_logger._context["user_id"], 42)
|
||||
self.assertEqual(self.context_logger._context["action"], "test")
|
||||
|
||||
def test_clear_context(self):
|
||||
"""Test context is cleared"""
|
||||
self.context_logger.set_context(user_id=42)
|
||||
self.context_logger.clear_context()
|
||||
|
||||
self.assertEqual(self.context_logger._context, {})
|
||||
|
||||
def test_context_updated_not_replaced(self):
|
||||
"""Test that set_context updates rather than replaces"""
|
||||
self.context_logger.set_context(user_id=42)
|
||||
self.context_logger.set_context(action="test")
|
||||
|
||||
self.assertEqual(self.context_logger._context["user_id"], 42)
|
||||
self.assertEqual(self.context_logger._context["action"], "test")
|
||||
|
||||
|
||||
class GetJsonLoggingConfigTest(TestCase):
|
||||
"""Tests for get_json_logging_config function"""
|
||||
|
||||
def test_returns_dict(self):
|
||||
"""Test function returns a dictionary"""
|
||||
config = get_json_logging_config()
|
||||
self.assertIsInstance(config, dict)
|
||||
|
||||
def test_has_required_keys(self):
|
||||
"""Test config has required keys"""
|
||||
config = get_json_logging_config()
|
||||
|
||||
self.assertIn("version", config)
|
||||
self.assertIn("formatters", config)
|
||||
self.assertIn("handlers", config)
|
||||
self.assertIn("loggers", config)
|
||||
|
||||
def test_json_formatter_configured(self):
|
||||
"""Test JSON formatter is configured"""
|
||||
config = get_json_logging_config()
|
||||
|
||||
self.assertIn("json", config["formatters"])
|
||||
self.assertEqual(
|
||||
config["formatters"]["json"]["()"],
|
||||
"apps.core.logging.JSONFormatter",
|
||||
)
|
||||
|
||||
def test_log_level_applied(self):
|
||||
"""Test log level is applied"""
|
||||
config = get_json_logging_config(log_level="DEBUG")
|
||||
|
||||
self.assertEqual(config["root"]["level"], "DEBUG")
|
||||
|
||||
def test_file_handler_added_when_path_provided(self):
|
||||
"""Test file handler is added when path is provided"""
|
||||
config = get_json_logging_config(log_file="/var/log/test.log")
|
||||
|
||||
self.assertIn("file", config["handlers"])
|
||||
self.assertEqual(
|
||||
config["handlers"]["file"]["filename"],
|
||||
"/var/log/test.log",
|
||||
)
|
||||
Reference in New Issue
Block a user