This document outlines the comprehensive development guidelines, coding conventions, and test-driven development practices for the Wanderline project.
- File names must be in English - No Japanese characters in filenames
- Comments must be in English - Do not use other languages in code comments
- Variable and function names - Use clear, descriptive English names
- Documentation - Update docs/ files appropriately for future reference
- Modularization - Consider splitting code if it exceeds 150 lines
- Clean code - Remove unused functions and variables
- Design decisions - Consider which code variants to keep vs remove
- File naming - Use clear, consistent naming conventions:
- β
Good:
config_v1.json,agent_vectorized.py - β Bad:
config_final.json,agent_new.py
- β
Good:
- Keep functions focused and single-purpose
- Use meaningful variable names that explain intent
- Group related functionality in modules
- Remove deprecated functions after confirming they're no longer needed
# Use uv for all Python operations
uv run python script.py # Execute Python files
uv run pytest # Run tests
uv add package_name # Add dependencies- Make small incremental changes - Don't try to implement everything at once
- Run tests frequently - After each logical change
- Execute code after implementation - Verify it works in practice
- Test before commit - Ensure all tests pass before committing
# Automatic test-and-commit workflow
scripts/test_and_commit.sh "feat: add white penalty to reward function and tests"
scripts/test_and_commit.sh "fix: resolve canvas rendering bug"
scripts/test_and_commit.sh "refactor: improve agent vectorization performance"Follow the RED-GREEN-REFACTOR cycle:
- π΄ RED: Write a failing test first
- π’ GREEN: Write minimal code to make the test pass
- π REFACTOR: Improve code quality while keeping tests green
def test_config_validation():
"""Test that invalid config keys are rejected."""
with pytest.raises(ValueError, match="Invalid config key"):
update_configs({"invalid_key": "value"}, validate_keys=True)def _validate_config_keys(changes, config_dir):
"""Validate that config keys exist."""
# Minimal implementation to pass test
if "invalid_key" in changes:
raise ValueError("Invalid config key: invalid_key")def _validate_config_keys(changes, config_dir):
"""Validate that config keys exist in at least one config file."""
config_path = Path(config_dir)
valid_keys = set()
# Collect all keys from existing config files
for config_file in config_path.glob("*.json"):
try:
with open(config_file, 'r') as f:
config = json.load(f)
valid_keys.update(config.keys())
except Exception:
continue
# Check if any change keys are invalid
invalid_keys = set(changes.keys()) - valid_keys
if invalid_keys:
raise ValueError(f"Invalid config key(s): {', '.join(invalid_keys)}")tests/
βββ test_canvas.py # Canvas operations
βββ test_agent.py # Agent algorithms
βββ test_config_updater.py # Configuration management
βββ test_reward.py # Reward functions
βββ test_integration.py # End-to-end workflows
Unit Tests - Test individual functions:
def test_apply_stroke_horizontal():
"""Test stroke application in horizontal direction."""
canvas = np.ones((100, 100, 3), dtype=np.uint8) * 255
result = apply_stroke(canvas, angle=0.0)
assert np.all(result[center_y, center_x] == [0, 0, 0])Integration Tests - Test module interactions:
def test_config_loading_with_agent():
"""Test complete workflow from config to agent."""
args = load_config_and_parse_args()
agent = create_agent(args)
assert agent is not NoneProperty Tests - Test with various inputs:
@pytest.mark.parametrize("angle", [0, np.pi/4, np.pi/2, np.pi])
def test_stroke_angles(angle):
"""Test stroke application at various angles."""
result = apply_stroke(canvas, angle=angle)
assert result is not None# Before starting work
uv run pytest
# After making changes
uv run pytest tests/test_module_you_changed.py
# Run specific test
uv run pytest tests/test_canvas.py::test_apply_stroke_horizontal -v
# Before committing
uv run pytest- Core functions (canvas, agent, reward): 100% coverage
- Configuration: 90% coverage
- Utilities: 80% coverage
- Integration: Key workflows covered
def test_function_name_scenario():
"""Test that function_name behaves correctly when scenario occurs."""
# Arrange - Set up test data
# Act - Execute the function
# Assert - Verify the results@pytest.fixture
def sample_canvas():
"""Provide standard test canvas."""
return np.ones((100, 100, 3), dtype=np.uint8) * 255
@pytest.fixture
def temp_config_dir():
"""Provide temporary config directory."""
with tempfile.TemporaryDirectory() as temp_dir:
# Setup test configs
yield temp_dir# Good: Specific assertions
assert config["steps"] == 1000
assert len(results) == 3
# Better: Descriptive error messages
assert config["steps"] == 1000, f"Expected steps=1000, got {config['steps']}"
# Best: Use pytest helpers
assert result == pytest.approx(expected, rel=1e-5)-
Write the test first (RED):
def test_new_stroke_validation(): with pytest.raises(ValueError): apply_stroke(canvas, angle=-1) # Invalid angle
-
Run the test - it should fail:
uv run pytest tests/test_canvas.py::test_new_stroke_validation -v
-
Write minimal implementation (GREEN):
def apply_stroke(canvas, angle): if angle < 0: raise ValueError("Angle must be non-negative") # Rest of implementation
-
Run test again - it should pass
-
Refactor while keeping tests green:
def apply_stroke(canvas, angle): if not (0 <= angle < 2 * np.pi): raise ValueError(f"Angle must be in [0, 2Ο), got {angle}") # Improved validation with better range checking
Use the config updater for batch modifications:
# Update all config files
uv run python scripts/update_configs.py --set steps=1000
# Update specific files
uv run python scripts/update_configs.py --set opacity=0.5 --files default.json long_run.json
# Update with pattern matching
uv run python scripts/update_configs.py --set duration=10.0 --pattern "quick_*.json"
# Preview changes without applying
uv run python scripts/update_configs.py --set steps=500 --dry-run
# Show differences from backups
uv run python scripts/update_configs.py --show-diff
# Restore from backups
uv run python scripts/update_configs.py --restore- Update
docs/files when adding new features - Remove obsolete documentation when deprecating features
- Keep
CLAUDE.mdcurrent with new commands and workflows - Propose removal of outdated content in discussions
- Commit documentation changes with code changes
- Use descriptive commit messages for documentation updates
- Keep documentation in sync with implementation
- Use memory-efficient mode for long runs (>1000 steps)
- Monitor memory usage during development
- Profile performance-critical code paths
- Check for unused imports and functions
- Verify test coverage for new features
- Ensure error handling is appropriate
- Validate that documentation is updated
# Run all tests
uv run pytest
# Run specific test file
uv run pytest tests/test_canvas.py
# Run with verbose output
uv run pytest tests/test_canvas.py -v
# Test and commit if passing
scripts/test_and_commit.sh "your commit message"
# Update config files
uv run python scripts/update_configs.py --set key=value- Write failing test first (RED)
- Implement minimal solution (GREEN)
- Refactor for quality (REFACTOR)
- All tests pass
- Documentation updated
- Commit changes
This comprehensive guide ensures consistent, high-quality development practices across the Wanderline project.