# 09 — Testing ## Required before merge ```bash go test ./... ``` All tests must pass before any change is merged. ## Where to add tests | Change area | Test location | |-------------|---------------| | Collectors | `internal/collector/*_test.go` | | HTTP handlers | `internal/server/*_test.go` | | Exporters | `internal/exporter/*_test.go` | | Parsers | `internal/parser/vendors//*_test.go` | ## Exporter tests The Reanimator exporter has comprehensive coverage: | Test file | Coverage | |-----------|----------| | `reanimator_converter_test.go` | Unit tests per conversion function | | `reanimator_integration_test.go` | Full export with realistic `AnalysisResult` | Run exporter tests only: ```bash go test ./internal/exporter/... go test ./internal/exporter/... -v -run Reanimator go test ./internal/exporter/... -cover ``` ## Guidelines - Prefer table-driven tests for parsing logic (multiple input variants). - Do not rely on network access in unit tests. - Test both the happy path and edge cases (missing fields, empty collections). - When adding a new vendor parser, include at minimum: - `Detect()` test with a positive and a negative sample file list. - `Parse()` test with a minimal but representative archive. ## Dedup and filtering functions — mandatory coverage Any function that deduplicates, filters, or classifies hardware inventory items **must** have tests covering all three axes before the code is considered done: | Axis | What to test | Why | |------|-------------|-----| | **True positive** | Items that ARE duplicates are collapsed to one | Proves the function works | | **True negative** | Items that are NOT duplicates are kept separate | Proves the function doesn't over-collapse | | **Counter-case** | The scenario that motivated the original code still works after changes | Prevents regression from future fixes | ### Worked example — GPU dedup regression (2026-03-11) `collectGPUsFromProcessors` was added for MSI (chassis Id matches processor Id). No tests → when Supermicro HGX arrived (chassis Id = "HGX_GPU_SXM_1", processor Id = "GPU_SXM_1"), the chassis lookup silently returned nothing, serial stayed empty, UUID was new → 8 duplicate GPUs. Simultaneously, fixing `gpuDocDedupKey` to use `slot|model` before path collapsed two distinct GraphicsControllers GPUs with the same model into one — breaking an existing test that had no counter-case for the path-fallback scenario. **Required test matrix for any dedup function:** ``` TestXxx_CollapsesDuplicates — same item via two sources → 1 result TestXxx_KeepsDistinct — two different items with same model → 2 results TestXxx_ — the specific vendor/setup that triggered the code ``` ### Practical rule When you write a new filter/dedup/classify function, ask: 1. Does my test cover the vendor that motivated this code? 2. Does my test cover a *different* vendor or naming convention where the function must NOT fire? 3. If I change the dedup key logic, do existing tests still exercise the old correct behavior? If any answer is "no" — add the missing test before committing.