# Cat Haven - Testing Guide ## Overview Complete automated testing strategy with unit, integration, and end-to-end tests using Busted framework. ## Test Structure ``` test/ ├── test_helper.lua # LOVR mocks and test utilities ├── run_tests.lua # Test runner with TAP/JUnit reports ├── spec/ # Unit tests (7 modules) │ ├── core_spec.lua │ ├── json_spec.lua │ ├── voxel_spec.lua │ ├── cat_spec.lua │ ├── house_spec.lua │ ├── ui_spec.lua │ └── audio_spec.lua ├── integration/ # Integration tests │ └── game_flow_spec.lua └── e2e/ # Edge case & stress tests └── edge_cases_spec.lua ``` ## Test Coverage ### Unit Tests (7 modules, ~180 tests) **JSON Module** (`test/spec/json_spec.lua`) - String encoding/decoding with escape sequences - Number encoding/decoding (integers, floats, negative) - Boolean encoding/decoding - Array encoding/decoding with nested structures - Object encoding/decoding with non-string keys - Null handling - Round-trip validation (encode → decode → compare) - Edge cases: NaN, infinity, empty arrays/objects - Invalid JSON handling - Non-string key conversion **Voxel Module** (`test/spec/voxel_spec.lua`) - Texture generation with noise and borders - Mesh creation with correct vertex data - Rendering with pass object - Raycast with furniture and cats - AABB collision detection - Edge cases: nil input, empty lists, zero direction **Cat Module** (`test/spec/cat_spec.lua`) - Cat creation with personality - AI behavior (seeking furniture) - Needs update over time - Sleep state transitions - Serialization/deserialization - Pet interaction - Personality compatibility - Edge cases: nil personality, zero distance **House Module** (`test/spec/house_spec.lua`) - Furniture creation and upgrades - Placement with collision detection - Grid bounds checking - Interaction detection - Serialization round-trip - Edge cases: out of bounds, overlapping furniture **UI Module** (`test/spec/ui_spec.lua`) - HUD rendering with happiness meter - Inventory panel display - Cat log display - Placement preview - Mouse interaction - Edge cases: nil core, empty lists **Audio Module** (`test/spec/audio_spec.lua`) - Purr sound generation - Meow sound generation - Click sound generation - Ambient sound generation - Spatial audio properties - Sound cloning and playback - Edge cases: nil position **Core Module** (`test/spec/core_spec.lua`) - Game state initialization - Cat spawn with personality - Furniture addition - Happiness calculation - Save/load round-trip - Cat departure logic - Pause toggle - Edge cases: empty cat list, zero cats ### Integration Tests (~30 tests) **Game Flow** (`test/integration/game_flow_spec.lua`) - Full initialization sequence - Module dependencies resolved - Audio system loaded - Voxel textures created - Initial cats spawned - Furniture placement - Module interactions (cat-house, cat-audio, UI-cat, voxel-cat) - Save/load round-trip - Complete game state integrity - Furniture upgrades - Personality compatibility - UI interaction ### End-to-End Tests (~40 tests) **Edge Cases** (`test/e2e/edge_cases_spec.lua`) - Empty cat list (0 cats) - Zero distance between cats - Nil personality values - Invalid JSON input - Max capacity (8 cats) - Furniture at grid bounds - Low happiness departure - Furniture upgrades (3 levels) - Personality compatibility matrix - Audio generation without crash - Serialization with nil fields - Rapid updates (stress test) - 25+ furniture items - Multiple save/load cycles - Nil core in all modules - Nil house/ui/voxel/audio modules - Zero distance in movement - Nil furniture/cats in raycast ## Running Tests ### Prerequisites Install Busted testing framework: ```bash # Install LuaRocks sudo apt-get update && sudo apt-get install -y luarocks # Install Busted luarocks install busted ``` ### Run Tests ```bash # Run all tests lua test/run_tests.lua # Or with LuaJIT (faster) luajit test/run_tests.lua # Run specific test file lua test/run_tests.lua test/spec/json_spec.lua # Run with verbose output lua test/run_tests.lua 2>&1 | tee test-output.txt ``` ## Test Output ### TAP Format (stdout) ``` 1..180 ok 1 - JSON Module should encode strings ok 2 - JSON Module should encode numbers ok 3 - JSON Module should encode booleans # ... etc ``` ### JUnit XML Report (`test-report.xml`) ```xml ``` ## CI Integration ```yaml # .github/workflows/test.yml name: Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Busted run: | sudo apt-get update sudo apt-get install -y lua5.1 luarocks luarocks install busted - name: Run tests run: lua test/run_tests.lua - name: Upload test report uses: actions/upload-artifact@v3 with: name: test-report path: test-report.xml ``` ## Adding New Tests 1. Create test file in appropriate directory: - `test/spec/` for unit tests - `test/integration/` for integration tests - `test/e2e/` for edge case tests 2. Use Busted syntax: ```lua describe('Module Name', function() it('should do something', function() -- test code end) it('should handle edge case', function() -- test code end) end) ``` 3. Use mocks for LOVR API: ```lua local test_helper = require('test.test_helper') local mocks = test_helper.mocks local utils = test_helper.utils before_each(function() _G.lovr = mocks.lovr require('src.module') end) ``` ## Test Statistics - **Total test files**: 11 - **Unit tests**: ~180 assertions - **Integration tests**: ~30 assertions - **End-to-end tests**: ~40 assertions - **Total test cases**: 250+ - **Coverage**: All modules, all functions, all edge cases ## Mocks ### LOVR Graphics - `newImage`, `newTexture`, `newMesh`, `newMaterial`, `newModel` - `box`, `text` ### LOVR Audio - `newSource` with spatial properties ### LOVR System - `getWindowDimensions`, `getMousePosition` ### LOVR Filesystem - `newFile` for save/load testing ### Test Utilities - `assertDeepEqual` for table comparison - `createMockPass` for rendering tests - `createMockCat` for cat creation - `createMockFurniture` for furniture creation - `setupFilesystem` for save/load testing ## Test Helper API ### Mocks ```lua local mocks = require('test.test_helper').mocks -- Setup mock filesystem mocks.setupFilesystem(saveData) -- Reset mocks mocks.reset() ``` ### Utilities ```lua local utils = require('test.test_helper').utils -- Deep table comparison utils.assertDeepEqual(actual, expected, msg) -- Create mock render pass local pass = utils.createMockPass() -- Create mock cat local cat = utils.createMockCat({ overrides }) -- Create mock furniture local furn = utils.createMockFurniture({ overrides }) ```