# GisConverter.TestsApp Comprehensive test project containing unit, integration and acceptance tests for the GisConverter solution. This README documents what is tested, project structure, how to run and debug tests locally, CI guidance, and how to add new tests or sample data. Table of contents - Purpose - What is tested - Project structure - How to run tests - Test conventions and patterns - Test data and samples - Integration gating and licensing - Debugging & diagnostics - Detection vs filesystem validation - Adding tests and samples - CI guidance - Troubleshooting - Contact ## Purpose This project validates correctness and resilience of the conversion tooling including: - Format detection and routing (which converter to use for given inputs) - File/archive handling and safe extraction logic (zip-slip protection) - End-to-end conversions for representative small sample artifacts - Command-line parsing and `Program.Run` behavior for the ConsoleApp ## What is tested - Unit tests - Detection heuristics (`FactoryHelpers`, `JsonFormatDetector`), routing (`ConverterFactory`), and `ConverterUtils` helpers. - Fast, deterministic tests that do not require heavy dependencies. - Integration tests - End-to-end converter flows (CSV, Shapefile, GML and other supported formats) using small on-disk sample artifacts. - CLI/Program tests that invoke `Program.Run(string[])` via reflection to validate parsing and behavior without terminating the test process. - Logging & diagnostics - Tests that assert logging messages are emitted at expected levels (Debug/Info/Warn/Error). Use `TestLogger` and `LogAssert` helpers. ## Project structure - `Converters` — converter-focused unit and integration tests. - `Factories` — unit tests for `ConverterFactory`, `FactoryHelpers` and input-detection helpers. - `Helpers` / `TestSupport` — shared helpers and constants (`IntegrationTestConstants`, `TestLogger`, `LogAssert`). - `TestData` — sample artifacts used by integration tests (kept small and optionally not committed). - `Licensing` — guidance and helpers around Aspose license application (licensed tests are gated). - `Models` — tests and helpers around `ConversionResult`, `FileExtensionHelpers` and related model types. ## How to run tests - IDE (Visual Studio / Rider) - Build solution and run tests via Test Explorer. - Ensure the ConsoleApp project is built when running CLI/Program tests because tests probe ConsoleApp build outputs. - dotnet CLI - From repository root: ```bash dotnet build dotnet test ./GisConverter.TestsApp/GisConverter.TestsApp.csproj ``` - Run a single test - Use the test runner or: ```bash dotnet test --filter "FullyQualifiedName~TestName" ``` ## Test conventions and patterns - Unique temp roots - Create a unique temporary root per test: `Path.GetTempPath()` + GUID; delete it in `Dispose()` (best-effort) to avoid interference. - Non-destructive assertions - Integration tests assert presence of output files (one or more) rather than exact file names. Use `FileExtensionHelpers` to compute expected extensions. - API usage - Prefer `IConverterFactory.TryCreate(...)` in CLI-like and test flows; use `Create(...)` when asserting suggestion behavior and exceptions. - Logging assertions - Capture logs with `TestLogger` and assert using `LogAssert.ContainsMessage(logger, level, token)` (case-insensitive substring checks are recommended). ## Test data and samples - Location: `TestData/` (for example `TestData/Shapefile`). - csproj: mark samples with `PreserveNewest` so they are available at runtime. - Keep samples small (KB–MB) and avoid committing proprietary datasets. Integration tests must check for sample presence and skip when absent. ## Integration gating and licensing - Gate heavier or licensed integration tests behind an opt-in environment variable to keep main CI fast and public-friendly: - `GISCONVERTER_ENABLE_INTEGRATION=1` — run gated integration tests. - `GISCONVERTER_ASPOSE_LICENSE_PATH` — optional file path to an Aspose license for licensed runs. - License guidance - Do NOT commit license files to source control. Provision licenses via secure CI secrets when running licensed integration pipelines. - Tests that require a license should check `AsposeLicenseManager.ApplyLicense()` (or the environment variable) and skip when licensing is unavailable. ## Debugging & diagnostics - Console capture - CLI tests capture `Console.Out` and `Console.Error` using `StringWriter`. Combine both streams when diagnosing failures. - Reflection probe diagnostics - When `Program` cannot be found the helper prints probed locations. Inspect those paths to ensure ConsoleApp build outputs exist. - Log capture - Use `TestLogger` to capture `Debug/Info/Warn/Error` output. When investigating failures include captured logs in issues. ## Detection vs filesystem validation - Overview - The ConsoleApp performs format detection (tries to resolve a converter for the provided input token) before it performs the filesystem existence check on the input path. This ordering preserves repair logic (for example joining adjacent tokens for unquoted paths) and provides richer diagnostic messages when parsing or detection fails. - Why this matters for tests - Some tests intentionally use synthetic or non-existent input paths to validate parsing and detection. Because detection runs before the existence check, those tests may observe detection-related messages (for example `Unable to auto-detect converter from input` or a detector reason) instead of an immediate `input path not found` diagnostic. - Tests that assert CLI negative flows should be tolerant of either detection/usage messages OR an input-not-found message—both are valid outcomes depending on test input and the CLI code path. - Recommended test assertion pattern - Combine stdout/stderr and assert that the combined output contains one of the expected diagnostics. Example: ```csharp var combined = stdout + "\n" + stderr; Assert.True( combined.Contains("Unable to auto-detect converter from input", StringComparison.OrdinalIgnoreCase) || combined.Contains("Detector reason", StringComparison.OrdinalIgnoreCase) || combined.Contains("Usage", StringComparison.OrdinalIgnoreCase) || combined.Contains("input path not found", StringComparison.OrdinalIgnoreCase), $"Unexpected CLI output:\n{combined}"); ``` - When you need deterministic path validation behavior - If a test specifically expects the CLI to reject a missing path, create the filesystem state required for that branch (for example, create a file or directory when validating positive cases or ensure the path is missing when validating rejection) before invoking `Program.Run`. - CLI guidance for consumers - The detect-then-validate order improves developer ergonomics and helps the CLI provide actionable guidance when users mistype or omit options. If you rely on immediate filesystem validation semantics, update your callers/tests to supply valid paths when you want existence checks to occur immediately. ## Adding tests and samples - Unit tests - Add deterministic unit tests under the appropriate folder. Use fakes to avoid heavy dependencies on Aspose or other drivers. - Integration tests 1. Add small sample artifacts under `TestData/` and set `PreserveNewest`. 2. Use `IntegrationTestConstants` to locate samples in tests. 3. Create unique temp `output` and `temp` folders and clean them up in `Dispose()`. 4. Assert presence of output files or appropriate `ConversionResult.Failure` messages. ## CI guidance - Keep most tests unlicensed and fast for main CI. - Run licensed/integration scenarios in separate pipelines or matrix jobs that provision secrets and samples. - Mark long-running or flaky tests so CI can opt-out when needed. ## Troubleshooting checklist - Missing `Program` type in CLI tests: ensure ConsoleApp is built and its assembly is present in probed output directories. - Missing sample files: verify `CopyToOutputDirectory` is set and files exist in test output. - Failing logging assertions: dump `TestLogger` messages and assert on stable tokens rather than exact messages. ## Contact - File an issue including: failing test name and stack trace, captured stdout/stderr, `TestLogger` output and sample file paths if relevant. This document is the canonical reference for contributors adding and maintaining tests in `GisConverter.TestsApp`. Update README entries when adding new test data sets, gating flags, or helper APIs.