add logging
This commit is contained in:
@@ -21,6 +21,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
- Match-3 debug controls include gem count adjustment and board reroll
|
||||
- Difficulty presets: Easy (3 gems), Normal (5 gems), Hard (8 gems)
|
||||
- Gameplay mode switching: Space+Enter in game scene switches between match-3 and clickomania modes
|
||||
- Test scripts located in `tests/` directory for system validation
|
||||
- Use `test_logging.gd` to validate the logging system functionality
|
||||
|
||||
### Audio Configuration
|
||||
- Music: Located in `assets/audio/music/` directory with loop configuration in AudioManager
|
||||
@@ -51,11 +53,19 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
- Use F12 key for global debug toggle
|
||||
- Remove debug prints before committing unless permanently useful
|
||||
|
||||
### Logging System Usage
|
||||
- **ALWAYS** use `DebugManager` logging functions instead of `print()`, `push_error()`, etc.
|
||||
- Use appropriate log levels: INFO for general messages, WARN for issues, ERROR for failures
|
||||
- Include meaningful categories to organize log output: `"GameManager"`, `"Match3"`, `"Settings"`
|
||||
- Leverage structured logging for better debugging and production monitoring
|
||||
- Use `DebugManager.set_log_level()` to control verbosity during development and testing
|
||||
|
||||
## Important File References
|
||||
|
||||
### Documentation Structure
|
||||
- **`docs/MAP.md`** - Complete project architecture and structure
|
||||
- **`docs/CODE_OF_CONDUCT.md`** - Coding standards and best practices
|
||||
- **`docs/TESTING.md`** - Testing guidelines and conventions
|
||||
- **This file** - Claude Code specific development guidelines
|
||||
|
||||
### Key Scripts to Understand
|
||||
@@ -78,12 +88,27 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
- Test debug UI with F12 toggle
|
||||
- Verify scene transitions work correctly
|
||||
- Check mobile compatibility if UI changes made
|
||||
- Use relevant test scripts from `tests/` directory to validate system functionality
|
||||
- Run `test_logging.gd` after making changes to the logging system
|
||||
|
||||
### Common Implementation Patterns
|
||||
- Scene transitions: Use `GameManager.start_game_with_mode()` and related methods
|
||||
- Debug integration: Connect to `DebugManager` signals and initialize debug state
|
||||
- Logging: Use `DebugManager.log_*()` functions with appropriate levels and categories
|
||||
- Gameplay modes: Implement in `scenes/game/gameplays/` directory following modular pattern
|
||||
- Scoring system: Connect `score_changed` signal from gameplay to main game scene
|
||||
- Settings: Use `SettingsManager` for persistent configuration
|
||||
- Audio: Use `AudioManager` for music and sound effects
|
||||
- Localization: Use `LocalizationManager` for language switching
|
||||
- Localization: Use `LocalizationManager` for language switching
|
||||
|
||||
### Logging Best Practices
|
||||
```gdscript
|
||||
# ✅ Good logging practices
|
||||
DebugManager.log_info("Scene transition completed", "GameManager")
|
||||
DebugManager.log_warn("Settings file not found, using defaults", "Settings")
|
||||
DebugManager.log_error("Failed to load audio resource: " + audio_path, "AudioManager")
|
||||
|
||||
# ❌ Avoid these patterns
|
||||
print("debug") # Use structured logging instead
|
||||
push_error("error") # Use DebugManager.log_error() with category
|
||||
```
|
||||
|
||||
@@ -123,8 +123,8 @@ func some_deep_function():
|
||||
|
||||
### Debug System Integration
|
||||
- Always connect to DebugManager signals for debug UI
|
||||
- Use debug prints with clear prefixes
|
||||
- Remove debug prints before committing (unless permanently useful)
|
||||
- Use structured logging instead of plain print statements
|
||||
- Remove temporary debug logs before committing (unless permanently useful)
|
||||
|
||||
```gdscript
|
||||
# ✅ Correct debug integration
|
||||
@@ -132,27 +132,47 @@ func _connect_to_global_debug() -> void:
|
||||
DebugManager.debug_ui_toggled.connect(_on_debug_ui_toggled)
|
||||
debug_ui.visible = DebugManager.is_debug_ui_visible()
|
||||
|
||||
# ✅ Good debug prints
|
||||
print("Match3: Debug UI toggled to: ", visible)
|
||||
print("TileSystem: Initialized ", tiles.size(), " tiles")
|
||||
# ✅ Good structured logging
|
||||
DebugManager.log_debug("Debug UI toggled to: " + str(visible), "Match3")
|
||||
DebugManager.log_info("Initialized " + str(tiles.size()) + " tiles", "TileSystem")
|
||||
|
||||
# ❌ Bad debug prints
|
||||
print("test") # Not descriptive
|
||||
print(some_variable) # No context
|
||||
# ❌ Bad logging practices
|
||||
print("test") # Not descriptive, use structured logging
|
||||
print(some_variable) # No context, use proper log level
|
||||
```
|
||||
|
||||
### Logging Standards
|
||||
- **ALWAYS** use `DebugManager.log_*()` functions instead of `print()` or `push_error()`
|
||||
- Choose appropriate log levels based on message importance and audience
|
||||
- Include meaningful categories to organize log output by system/component
|
||||
- Format messages with clear, descriptive text and relevant context
|
||||
|
||||
```gdscript
|
||||
# ✅ Correct logging usage
|
||||
DebugManager.log_info("Game scene loaded successfully", "SceneManager")
|
||||
DebugManager.log_warn("Audio file not found, using default", "AudioManager")
|
||||
DebugManager.log_error("Failed to save settings: " + error_message, "Settings")
|
||||
|
||||
# ❌ Wrong approaches
|
||||
print("loaded") # Use DebugManager.log_info() with category
|
||||
push_error("error") # Use DebugManager.log_error() with context
|
||||
if debug_mode: print("debug info") # Use DebugManager.log_debug()
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
- Always check if resources loaded successfully
|
||||
- Use `push_error()` for critical failures
|
||||
- Use `DebugManager.log_error()` for critical failures
|
||||
- Provide fallback behavior when possible
|
||||
- Include meaningful context in error messages
|
||||
|
||||
```gdscript
|
||||
# ✅ Correct error handling
|
||||
# ✅ Correct error handling with structured logging
|
||||
func load_scene(path: String) -> void:
|
||||
var packed_scene := load(path)
|
||||
if not packed_scene or not packed_scene is PackedScene:
|
||||
push_error("Failed to load scene at: %s" % path)
|
||||
DebugManager.log_error("Failed to load scene at: %s" % path, "SceneLoader")
|
||||
return
|
||||
DebugManager.log_info("Successfully loaded scene: %s" % path, "SceneLoader")
|
||||
get_tree().change_scene_to_packed(packed_scene)
|
||||
```
|
||||
|
||||
@@ -253,10 +273,12 @@ func _process(delta):
|
||||
```gdscript
|
||||
# ❌ Don't create separate debug systems
|
||||
var my_debug_enabled = false
|
||||
print("debug: " + some_info) # Don't use plain print()
|
||||
|
||||
# ✅ Use the global debug system
|
||||
# ✅ Use the global debug and logging systems
|
||||
if DebugManager.is_debug_enabled():
|
||||
show_debug_info()
|
||||
DebugManager.log_debug("Debug information: " + some_info, "MyComponent")
|
||||
```
|
||||
|
||||
## Learning Resources
|
||||
@@ -294,4 +316,4 @@ This code of conduct emphasizes:
|
||||
- **Integration**: Use the project's systems properly
|
||||
- **Learning**: Continuously improve your skills
|
||||
|
||||
Remember: It's better to ask questions and write clear, simple code than to guess and create complex, hard-to-maintain solutions. The goal is to contribute effectively to a codebase that will grow and evolve over time.
|
||||
Remember: It's better to ask questions and write clear, simple code than to guess and create complex, hard-to-maintain solutions. The goal is to contribute effectively to a codebase that will grow and evolve over time.
|
||||
|
||||
77
docs/MAP.md
77
docs/MAP.md
@@ -15,8 +15,9 @@ skelly/
|
||||
├── localization/ # Internationalization files
|
||||
├── scenes/ # Godot scenes (.tscn) and scripts (.gd)
|
||||
├── src/ # Source code organization
|
||||
├── project.godot # Main Godot project configuration
|
||||
└── icon.svg # Project icon
|
||||
├── tests/ # Test scripts and validation utilities
|
||||
├── project.godot # Main Godot project configuration
|
||||
└── icon.svg # Project icon
|
||||
```
|
||||
|
||||
## Core Architecture
|
||||
@@ -48,10 +49,13 @@ Located in `src/autoloads/`, these scripts are automatically loaded when the gam
|
||||
- Uses translation files in `localization/`
|
||||
|
||||
5. **DebugManager** (`src/autoloads/DebugManager.gd`)
|
||||
- Global debug state management
|
||||
- Global debug state management and centralized logging system
|
||||
- Debug UI visibility control
|
||||
- F12 toggle functionality
|
||||
- Signal-based debug system
|
||||
- Structured logging with configurable log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
|
||||
- Timestamp-based log formatting with category support
|
||||
- Runtime log level filtering for development and production builds
|
||||
|
||||
## Scene Hierarchy & Flow
|
||||
|
||||
@@ -175,11 +179,23 @@ assets/
|
||||
### Game Data (`data/`)
|
||||
- `default_bus_layout.tres` - Audio bus configuration for Godot
|
||||
|
||||
### Documentation (`docs/`)
|
||||
- `MAP.md` - Project architecture and structure overview
|
||||
- `CLAUDE.md` - Claude Code development guidelines
|
||||
- `CODE_OF_CONDUCT.md` - Coding standards and best practices
|
||||
- `TESTING.md` - Testing guidelines and conventions
|
||||
|
||||
### Localization (`localization/`)
|
||||
- `languages.json` - Available language definitions
|
||||
- `MainStrings.en.translation` - English translations
|
||||
- `MainStrings.ru.translation` - Russian translations
|
||||
|
||||
### Testing & Validation (`tests/`)
|
||||
- `test_logging.gd` - DebugManager logging system validation
|
||||
- `README.md` - Brief directory overview (see docs/TESTING.md for full guidelines)
|
||||
- Future test scripts for individual components and integration testing
|
||||
- Temporary test utilities for development and debugging
|
||||
|
||||
### Project Configuration
|
||||
- `project.godot` - Main Godot project settings
|
||||
- Autoload definitions
|
||||
@@ -215,6 +231,58 @@ SettingsManager --> localization/languages.json
|
||||
AudioManager --> data/default_bus_layout.tres
|
||||
```
|
||||
|
||||
## Logging System
|
||||
|
||||
The project uses a centralized logging system implemented in DebugManager for consistent, structured logging throughout the application.
|
||||
|
||||
### Log Levels
|
||||
```
|
||||
TRACE (0) - Detailed execution tracing (debug mode only)
|
||||
DEBUG (1) - Development debugging information (debug mode only)
|
||||
INFO (2) - General application information (always visible)
|
||||
WARN (3) - Warning messages that don't break functionality
|
||||
ERROR (4) - Error conditions that may affect functionality
|
||||
FATAL (5) - Critical errors that may cause application failure
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
```gdscript
|
||||
# Basic logging with automatic categorization
|
||||
DebugManager.log_info("Game started successfully")
|
||||
DebugManager.log_warn("Settings file not found, using defaults")
|
||||
DebugManager.log_error("Failed to load audio resource")
|
||||
|
||||
# Logging with custom categories for better organization
|
||||
DebugManager.log_debug("Grid regenerated with 64 tiles", "Match3")
|
||||
DebugManager.log_info("Language changed to: en", "SettingsManager")
|
||||
DebugManager.log_error("Invalid scene path provided", "GameManager")
|
||||
```
|
||||
|
||||
### Log Format
|
||||
```
|
||||
[timestamp] LEVEL [category]: message
|
||||
Example: [2025-09-24T10:48:08] INFO [GameManager]: Loading main scene
|
||||
```
|
||||
|
||||
### Runtime Configuration
|
||||
```gdscript
|
||||
# Set minimum log level (filters out lower priority messages)
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.WARN)
|
||||
|
||||
# Get current log level
|
||||
var current_level = DebugManager.get_log_level()
|
||||
|
||||
# Check if a specific level would be logged
|
||||
if DebugManager._should_log(DebugManager.LogLevel.DEBUG):
|
||||
# Expensive debug calculation here
|
||||
```
|
||||
|
||||
### Integration with Godot Systems
|
||||
- **WARN/ERROR/FATAL** levels automatically call `push_warning()` and `push_error()`
|
||||
- **TRACE/DEBUG** levels only display when debug mode is enabled
|
||||
- **INFO** and higher levels always display regardless of debug mode
|
||||
- All levels respect the configured minimum log level threshold
|
||||
|
||||
## Development Notes
|
||||
|
||||
### Current Implementation Status
|
||||
@@ -233,5 +301,6 @@ AudioManager --> data/default_bus_layout.tres
|
||||
5. **Data-Driven Configuration** - JSON for settings and translations
|
||||
6. **Component Architecture** - Reusable UI and game components
|
||||
7. **Centralized Scoring System** - Global score management across gameplay modes
|
||||
8. **Structured Logging System** - Centralized logging with level-based filtering and formatted output
|
||||
|
||||
This structure provides a clean separation of concerns, making the codebase maintainable and extensible for future features.
|
||||
This structure provides a clean separation of concerns, making the codebase maintainable and extensible for future features.
|
||||
|
||||
156
docs/TESTING.md
Normal file
156
docs/TESTING.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Tests Directory
|
||||
|
||||
This directory contains test scripts and utilities for validating various systems and components in the Skelly project.
|
||||
|
||||
## Overview
|
||||
|
||||
The `tests/` directory is designed to house:
|
||||
- System validation scripts
|
||||
- Component testing utilities
|
||||
- Integration tests
|
||||
- Performance benchmarks
|
||||
- Debugging tools
|
||||
|
||||
## Current Test Files
|
||||
|
||||
### `test_logging.gd`
|
||||
Comprehensive test script for the DebugManager logging system.
|
||||
|
||||
**Features:**
|
||||
- Tests all log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
|
||||
- Validates log level filtering functionality
|
||||
- Tests category-based logging organization
|
||||
- Verifies debug mode integration
|
||||
- Demonstrates proper logging usage patterns
|
||||
|
||||
**Usage:**
|
||||
```gdscript
|
||||
# Option 1: Add as temporary autoload
|
||||
# In project.godot, add: tests/test_logging.gd
|
||||
|
||||
# Option 2: Instantiate in a scene
|
||||
var test_script = preload("res://tests/test_logging.gd").new()
|
||||
add_child(test_script)
|
||||
|
||||
# Option 3: Run directly from editor
|
||||
# Open the script and run the scene containing it
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
The script will output formatted log messages demonstrating:
|
||||
- Proper timestamp formatting
|
||||
- Log level filtering behavior
|
||||
- Category organization
|
||||
- Debug mode dependency for TRACE/DEBUG levels
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
When creating new test files, follow these conventions:
|
||||
|
||||
### File Naming
|
||||
- Use descriptive names starting with `test_`
|
||||
- Example: `test_audio_manager.gd`, `test_scene_transitions.gd`
|
||||
|
||||
### File Structure
|
||||
```gdscript
|
||||
extends Node
|
||||
|
||||
# Brief description of what this test validates
|
||||
|
||||
func _ready():
|
||||
# Wait for system initialization if needed
|
||||
await get_tree().process_frame
|
||||
run_tests()
|
||||
|
||||
func run_tests():
|
||||
print("=== Starting [System Name] Tests ===")
|
||||
|
||||
# Individual test functions
|
||||
test_basic_functionality()
|
||||
test_edge_cases()
|
||||
test_error_conditions()
|
||||
|
||||
print("=== [System Name] Tests Complete ===")
|
||||
|
||||
func test_basic_functionality():
|
||||
print("\\n--- Test: Basic Functionality ---")
|
||||
# Test implementation
|
||||
|
||||
func test_edge_cases():
|
||||
print("\\n--- Test: Edge Cases ---")
|
||||
# Edge case testing
|
||||
|
||||
func test_error_conditions():
|
||||
print("\\n--- Test: Error Conditions ---")
|
||||
# Error condition testing
|
||||
```
|
||||
|
||||
### Testing Guidelines
|
||||
|
||||
1. **Independence**: Each test should be self-contained and not depend on other tests
|
||||
2. **Cleanup**: Restore original state after testing (settings, debug modes, etc.)
|
||||
3. **Clear Output**: Use descriptive print statements to show test progress
|
||||
4. **Error Handling**: Test both success and failure conditions
|
||||
5. **Documentation**: Include comments explaining complex test scenarios
|
||||
|
||||
### Integration with Main Project
|
||||
|
||||
- **Temporary Usage**: Test files are meant to be added temporarily during development
|
||||
- **Not in Production**: These files should not be included in release builds
|
||||
- **Autoload Testing**: Add to autoloads temporarily for automatic execution
|
||||
- **Manual Testing**: Run individually when testing specific components
|
||||
|
||||
## Test Categories
|
||||
|
||||
### System Tests
|
||||
Test core autoload managers and global systems:
|
||||
- `test_logging.gd` - DebugManager logging system
|
||||
- Future: `test_settings.gd` - SettingsManager functionality
|
||||
- Future: `test_audio.gd` - AudioManager functionality
|
||||
- Future: `test_scene_management.gd` - GameManager transitions
|
||||
|
||||
### Component Tests
|
||||
Test individual game components:
|
||||
- Future: `test_match3.gd` - Match-3 gameplay mechanics
|
||||
- Future: `test_tile_system.gd` - Tile behavior and interactions
|
||||
- Future: `test_ui_components.gd` - Menu and UI functionality
|
||||
|
||||
### Integration Tests
|
||||
Test system interactions and workflows:
|
||||
- Future: `test_game_flow.gd` - Complete game session flow
|
||||
- Future: `test_debug_system.gd` - Debug UI integration
|
||||
- Future: `test_localization.gd` - Language switching and translations
|
||||
|
||||
## Running Tests
|
||||
|
||||
### During Development
|
||||
1. Copy or symlink the test file to your scene
|
||||
2. Add as a child node or autoload temporarily
|
||||
3. Run the project and observe console output
|
||||
4. Remove from project when testing is complete
|
||||
|
||||
### Automated Testing
|
||||
While Godot doesn't have built-in unit testing, these scripts provide:
|
||||
- Consistent validation approach
|
||||
- Repeatable test scenarios
|
||||
- Clear pass/fail output
|
||||
- System behavior documentation
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Document Expected Behavior**: Include comments about what should happen
|
||||
2. **Test Boundary Conditions**: Include edge cases and error conditions
|
||||
3. **Measure Performance**: Add timing for performance-critical components
|
||||
4. **Visual Validation**: For UI components, include visual checks
|
||||
5. **Cleanup After Tests**: Restore initial state to avoid side effects
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new test files:
|
||||
1. Follow the naming and structure conventions
|
||||
2. Update this README with new test descriptions
|
||||
3. Ensure tests are self-contained and documented
|
||||
4. Test both success and failure scenarios
|
||||
5. Include performance considerations where relevant
|
||||
|
||||
This testing approach helps maintain code quality and provides validation tools for system changes and refactoring.
|
||||
@@ -7,4 +7,4 @@ func _ready():
|
||||
# Example: Add some score after a few seconds to test the system
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
score_changed.emit(100)
|
||||
print("Clickomania awarded 100 points")
|
||||
print("Clickomania awarded 100 points")
|
||||
|
||||
@@ -18,4 +18,4 @@ offset_bottom = 12.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
text = "Clickomania Gameplay (Demo)"
|
||||
horizontal_alignment = 1
|
||||
horizontal_alignment = 1
|
||||
|
||||
@@ -12,4 +12,4 @@ func _on_pressed():
|
||||
DebugManager.toggle_debug()
|
||||
|
||||
func _on_debug_toggled(enabled: bool):
|
||||
text = "Debug: " + ("ON" if enabled else "OFF")
|
||||
text = "Debug: " + ("ON" if enabled else "OFF")
|
||||
|
||||
@@ -15,4 +15,4 @@ offset_bottom = -10.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
text = "Debug: OFF"
|
||||
script = ExtResource("1_gn2ol")
|
||||
script = ExtResource("1_gn2ol")
|
||||
|
||||
@@ -19,7 +19,7 @@ func _ready():
|
||||
|
||||
var orig_stream = _load_stream()
|
||||
if not orig_stream:
|
||||
push_error("Failed to load music stream: %s" % MUSIC_PATH)
|
||||
DebugManager.log_error("Failed to load music stream: %s" % MUSIC_PATH, "AudioManager")
|
||||
return
|
||||
|
||||
var stream = orig_stream.duplicate(true) as AudioStream
|
||||
|
||||
@@ -2,16 +2,26 @@ extends Node
|
||||
|
||||
signal debug_toggled(enabled: bool)
|
||||
|
||||
enum LogLevel {
|
||||
TRACE = 0,
|
||||
DEBUG = 1,
|
||||
INFO = 2,
|
||||
WARN = 3,
|
||||
ERROR = 4,
|
||||
FATAL = 5
|
||||
}
|
||||
|
||||
var debug_enabled: bool = false
|
||||
var debug_overlay_visible: bool = false
|
||||
var current_log_level: LogLevel = LogLevel.INFO
|
||||
|
||||
func _ready():
|
||||
print("DebugManager loaded")
|
||||
log_info("DebugManager loaded")
|
||||
|
||||
func toggle_debug():
|
||||
debug_enabled = !debug_enabled
|
||||
debug_toggled.emit(debug_enabled)
|
||||
print("Debug mode: ", "ON" if debug_enabled else "OFF")
|
||||
log_info("Debug mode: " + ("ON" if debug_enabled else "OFF"))
|
||||
|
||||
func set_debug_enabled(enabled: bool):
|
||||
if debug_enabled != enabled:
|
||||
@@ -30,6 +40,70 @@ func set_overlay_visible(visible: bool):
|
||||
func is_overlay_visible() -> bool:
|
||||
return debug_overlay_visible
|
||||
|
||||
func log_debug(message: String, category: String = "DEBUG"):
|
||||
if debug_enabled:
|
||||
print("[", category, "] ", message)
|
||||
func set_log_level(level: LogLevel):
|
||||
current_log_level = level
|
||||
log_info("Log level set to: " + _log_level_to_string(level))
|
||||
|
||||
func get_log_level() -> LogLevel:
|
||||
return current_log_level
|
||||
|
||||
func _should_log(level: LogLevel) -> bool:
|
||||
return level >= current_log_level
|
||||
|
||||
func _log_level_to_string(level: LogLevel) -> String:
|
||||
match level:
|
||||
LogLevel.TRACE:
|
||||
return "TRACE"
|
||||
LogLevel.DEBUG:
|
||||
return "DEBUG"
|
||||
LogLevel.INFO:
|
||||
return "INFO"
|
||||
LogLevel.WARN:
|
||||
return "WARN"
|
||||
LogLevel.ERROR:
|
||||
return "ERROR"
|
||||
LogLevel.FATAL:
|
||||
return "FATAL"
|
||||
_:
|
||||
return "UNKNOWN"
|
||||
|
||||
func _format_log_message(level: LogLevel, message: String, category: String = "") -> String:
|
||||
var timestamp = Time.get_datetime_string_from_system()
|
||||
var level_str = _log_level_to_string(level)
|
||||
var category_str = (" [" + category + "]") if category != "" else ""
|
||||
return "[%s] %s%s: %s" % [timestamp, level_str, category_str, message]
|
||||
|
||||
func log_trace(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.TRACE):
|
||||
var formatted = _format_log_message(LogLevel.TRACE, message, category)
|
||||
if debug_enabled:
|
||||
print(formatted)
|
||||
|
||||
func log_debug(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.DEBUG):
|
||||
var formatted = _format_log_message(LogLevel.DEBUG, message, category)
|
||||
if debug_enabled:
|
||||
print(formatted)
|
||||
|
||||
func log_info(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.INFO):
|
||||
var formatted = _format_log_message(LogLevel.INFO, message, category)
|
||||
print(formatted)
|
||||
|
||||
func log_warn(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.WARN):
|
||||
var formatted = _format_log_message(LogLevel.WARN, message, category)
|
||||
print(formatted)
|
||||
push_warning(formatted)
|
||||
|
||||
func log_error(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.ERROR):
|
||||
var formatted = _format_log_message(LogLevel.ERROR, message, category)
|
||||
print(formatted)
|
||||
push_error(formatted)
|
||||
|
||||
func log_fatal(message: String, category: String = ""):
|
||||
if _should_log(LogLevel.FATAL):
|
||||
var formatted = _format_log_message(LogLevel.FATAL, message, category)
|
||||
print(formatted)
|
||||
push_error(formatted)
|
||||
|
||||
@@ -18,7 +18,7 @@ func start_game_with_mode(gameplay_mode: String) -> void:
|
||||
pending_gameplay_mode = gameplay_mode
|
||||
var packed_scene := load(GAME_SCENE_PATH)
|
||||
if not packed_scene or not packed_scene is PackedScene:
|
||||
push_error("Failed to load Game scene at: %s" % GAME_SCENE_PATH)
|
||||
DebugManager.log_error("Failed to load Game scene at: %s" % GAME_SCENE_PATH, "GameManager")
|
||||
return
|
||||
get_tree().change_scene_to_packed(packed_scene)
|
||||
# Wait one frame for the scene to be ready, then set gameplay mode
|
||||
@@ -27,14 +27,13 @@ func start_game_with_mode(gameplay_mode: String) -> void:
|
||||
get_tree().current_scene.set_gameplay_mode(pending_gameplay_mode)
|
||||
|
||||
func save_game() -> void:
|
||||
print("Game saved (mock)")
|
||||
DebugManager.log_info("Game saved (mock)", "GameManager")
|
||||
|
||||
func exit_to_main_menu() -> void:
|
||||
print("GameManager: Attempting to exit to main menu")
|
||||
DebugManager.log_info("Attempting to exit to main menu", "GameManager")
|
||||
var packed_scene := load(MAIN_SCENE_PATH)
|
||||
if not packed_scene or not packed_scene is PackedScene:
|
||||
push_error("Failed to load Main scene at: %s" % MAIN_SCENE_PATH)
|
||||
DebugManager.log_error("Failed to load Main scene at: %s" % MAIN_SCENE_PATH, "GameManager")
|
||||
return
|
||||
print("GameManager: Loading main scene")
|
||||
DebugManager.log_info("Loading main scene", "GameManager")
|
||||
get_tree().change_scene_to_packed(packed_scene)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ var default_settings = {
|
||||
var languages_data = {}
|
||||
|
||||
func _ready():
|
||||
print("SettingsManager ready")
|
||||
DebugManager.log_info("SettingsManager ready", "SettingsManager")
|
||||
load_languages()
|
||||
load_settings()
|
||||
|
||||
@@ -27,10 +27,10 @@ func load_settings():
|
||||
if config.load(SETTINGS_FILE) == OK:
|
||||
for key in default_settings.keys():
|
||||
settings[key] = config.get_value("settings", key, default_settings[key])
|
||||
print("Settings loaded: ", settings)
|
||||
DebugManager.log_info("Settings loaded: " + str(settings), "SettingsManager")
|
||||
else:
|
||||
print("No settings file found, using defaults")
|
||||
print("Language is set to: ", settings["language"])
|
||||
DebugManager.log_warn("No settings file found, using defaults", "SettingsManager")
|
||||
DebugManager.log_info("Language is set to: " + str(settings["language"]), "SettingsManager")
|
||||
TranslationServer.set_locale(settings["language"])
|
||||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db(settings["master_volume"]))
|
||||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), linear_to_db(settings["music_volume"]))
|
||||
@@ -42,7 +42,7 @@ func save_settings():
|
||||
for key in settings.keys():
|
||||
config.set_value("settings", key, settings[key])
|
||||
config.save(SETTINGS_FILE)
|
||||
print("Settings saved: ", settings)
|
||||
DebugManager.log_info("Settings saved: " + str(settings), "SettingsManager")
|
||||
|
||||
func get_setting(key: String):
|
||||
return settings.get(key)
|
||||
@@ -65,7 +65,7 @@ func _apply_setting_side_effect(key: String, value) -> void:
|
||||
func load_languages():
|
||||
var file = FileAccess.open(LANGUAGES_JSON_PATH, FileAccess.READ)
|
||||
if not file:
|
||||
print("Could not open languages.json")
|
||||
DebugManager.log_error("Could not open languages.json", "SettingsManager")
|
||||
return
|
||||
|
||||
var json_string = file.get_as_text()
|
||||
@@ -73,12 +73,12 @@ func load_languages():
|
||||
|
||||
var json = JSON.new()
|
||||
if json.parse(json_string) != OK:
|
||||
print("Error parsing languages.json")
|
||||
DebugManager.log_error("Error parsing languages.json", "SettingsManager")
|
||||
return
|
||||
|
||||
languages_data = json.data
|
||||
if languages_data.has("languages"):
|
||||
print("Languages loaded: ", languages_data.languages.keys())
|
||||
DebugManager.log_info("Languages loaded: " + str(languages_data.languages.keys()), "SettingsManager")
|
||||
|
||||
func get_languages_data():
|
||||
return languages_data
|
||||
|
||||
22
tests/README.md
Normal file
22
tests/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Tests Directory
|
||||
|
||||
This directory contains test scripts and validation utilities for the Skelly project.
|
||||
|
||||
## Documentation
|
||||
|
||||
For complete testing guidelines, conventions, and usage instructions, see:
|
||||
**[docs/TESTING.md](../docs/TESTING.md)**
|
||||
|
||||
## Current Files
|
||||
|
||||
- `test_logging.gd` - Comprehensive logging system validation script
|
||||
|
||||
## Quick Usage
|
||||
|
||||
```gdscript
|
||||
# Add as temporary autoload or run in scene
|
||||
var test_script = preload("res://tests/test_logging.gd").new()
|
||||
add_child(test_script)
|
||||
```
|
||||
|
||||
See [docs/TESTING.md](../docs/TESTING.md) for detailed usage instructions and conventions.
|
||||
106
tests/test_logging.gd
Normal file
106
tests/test_logging.gd
Normal file
@@ -0,0 +1,106 @@
|
||||
extends Node
|
||||
|
||||
# Test script for the DebugManager logging system
|
||||
# This script validates all log levels, filtering, and formatting functionality
|
||||
# Usage: Add to scene or autoload temporarily to run tests
|
||||
|
||||
func _ready():
|
||||
# Wait a frame for DebugManager to initialize
|
||||
await get_tree().process_frame
|
||||
test_logging_system()
|
||||
|
||||
func test_logging_system():
|
||||
print("=== Starting Logging System Tests ===")
|
||||
|
||||
# Test 1: Basic log level functionality
|
||||
test_basic_logging()
|
||||
|
||||
# Test 2: Log level filtering
|
||||
test_log_level_filtering()
|
||||
|
||||
# Test 3: Category functionality
|
||||
test_category_logging()
|
||||
|
||||
# Test 4: Debug mode integration
|
||||
test_debug_mode_integration()
|
||||
|
||||
print("=== Logging System Tests Complete ===")
|
||||
|
||||
func test_basic_logging():
|
||||
print("\n--- Test 1: Basic Log Level Functionality ---")
|
||||
|
||||
# Reset to INFO level for consistent testing
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
|
||||
|
||||
DebugManager.log_trace("TRACE: This should not appear (below INFO level)")
|
||||
DebugManager.log_debug("DEBUG: This should not appear (below INFO level)")
|
||||
DebugManager.log_info("INFO: This message should appear")
|
||||
DebugManager.log_warn("WARN: This warning should appear")
|
||||
DebugManager.log_error("ERROR: This error should appear")
|
||||
DebugManager.log_fatal("FATAL: This fatal error should appear")
|
||||
|
||||
func test_log_level_filtering():
|
||||
print("\n--- Test 2: Log Level Filtering ---")
|
||||
|
||||
# Test DEBUG level
|
||||
print("Setting log level to DEBUG...")
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.DEBUG)
|
||||
DebugManager.log_trace("TRACE: Should not appear (below DEBUG)")
|
||||
DebugManager.log_debug("DEBUG: Should appear with debug enabled")
|
||||
DebugManager.log_info("INFO: Should appear")
|
||||
|
||||
# Test ERROR level (very restrictive)
|
||||
print("Setting log level to ERROR...")
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.ERROR)
|
||||
DebugManager.log_debug("DEBUG: Should not appear (below ERROR)")
|
||||
DebugManager.log_warn("WARN: Should not appear (below ERROR)")
|
||||
DebugManager.log_error("ERROR: Should appear")
|
||||
DebugManager.log_fatal("FATAL: Should appear")
|
||||
|
||||
# Reset to INFO for remaining tests
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
|
||||
|
||||
func test_category_logging():
|
||||
print("\n--- Test 3: Category Functionality ---")
|
||||
|
||||
DebugManager.log_info("Message without category")
|
||||
DebugManager.log_info("Message with TEST category", "TEST")
|
||||
DebugManager.log_info("Message with LOGGING category", "LOGGING")
|
||||
DebugManager.log_warn("Warning with VALIDATION category", "VALIDATION")
|
||||
DebugManager.log_error("Error with SYSTEM category", "SYSTEM")
|
||||
|
||||
func test_debug_mode_integration():
|
||||
print("\n--- Test 4: Debug Mode Integration ---")
|
||||
|
||||
# Set to TRACE level to test debug mode dependency
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.TRACE)
|
||||
|
||||
var original_debug_state = DebugManager.is_debug_enabled()
|
||||
|
||||
# Test with debug mode OFF
|
||||
DebugManager.set_debug_enabled(false)
|
||||
print("Debug mode OFF - TRACE and DEBUG should not appear:")
|
||||
DebugManager.log_trace("TRACE: Should NOT appear (debug mode OFF)")
|
||||
DebugManager.log_debug("DEBUG: Should NOT appear (debug mode OFF)")
|
||||
DebugManager.log_info("INFO: Should appear regardless of debug mode")
|
||||
|
||||
# Test with debug mode ON
|
||||
DebugManager.set_debug_enabled(true)
|
||||
print("Debug mode ON - TRACE and DEBUG should appear:")
|
||||
DebugManager.log_trace("TRACE: Should appear (debug mode ON)")
|
||||
DebugManager.log_debug("DEBUG: Should appear (debug mode ON)")
|
||||
DebugManager.log_info("INFO: Should still appear")
|
||||
|
||||
# Restore original debug state
|
||||
DebugManager.set_debug_enabled(original_debug_state)
|
||||
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
|
||||
|
||||
# Helper function to validate log level enum values
|
||||
func test_log_level_enum():
|
||||
print("\n--- Log Level Enum Values ---")
|
||||
print("TRACE: ", DebugManager.LogLevel.TRACE)
|
||||
print("DEBUG: ", DebugManager.LogLevel.DEBUG)
|
||||
print("INFO: ", DebugManager.LogLevel.INFO)
|
||||
print("WARN: ", DebugManager.LogLevel.WARN)
|
||||
print("ERROR: ", DebugManager.LogLevel.ERROR)
|
||||
print("FATAL: ", DebugManager.LogLevel.FATAL)
|
||||
Reference in New Issue
Block a user