diff --git a/SatelliteProvider.Tests/Fixtures/TestCoordinates.cs b/SatelliteProvider.Tests/Fixtures/TestCoordinates.cs new file mode 100644 index 0000000..5da914a --- /dev/null +++ b/SatelliteProvider.Tests/Fixtures/TestCoordinates.cs @@ -0,0 +1,71 @@ +using SatelliteProvider.Common.DTO; + +namespace SatelliteProvider.Tests.Fixtures; + +public static class TestCoordinates +{ + public const double TileLat = 47.461747; + public const double TileLon = 37.647063; + public const int DefaultZoom = 18; + + public static GeoPoint TileCenter => new(TileLat, TileLon); + + public static class Region + { + public static (double Lat, double Lon, double SizeMeters, int Zoom, bool Stitch) Reg01 => + (47.461747, 37.647063, 200, 18, false); + + public static (double Lat, double Lon, double SizeMeters, int Zoom, bool Stitch) Reg02 => + (47.461747, 37.647063, 400, 17, false); + + public static (double Lat, double Lon, double SizeMeters, int Zoom, bool Stitch) Reg03 => + (47.461747, 37.647063, 500, 18, true); + } + + public static class Route + { + public static List<(double Lat, double Lon)> Route01Points => new() + { + (48.276067180586544, 37.38445758819581), + (48.27074009522731, 37.374029159545906), + }; + + public static List<(double Lat, double Lon)> Route04Points => new() + { + (48.276067180586544, 37.38445758819581), + (48.27074009522731, 37.374029159545906), + (48.263312668696855, 37.37707614898682), + (48.26539817051818, 37.36587524414063), + (48.25851283439989, 37.35952377319337), + (48.254426906081555, 37.374801635742195), + (48.25914140977405, 37.39068031311036), + (48.25354110233028, 37.401752471923835), + (48.25902712391726, 37.416257858276374), + (48.26828345053738, 37.402009963989265), + }; + + public static List<(double Lat, double Lon)> Route06Points => new() + { + (48.276067180586544, 37.51945758819581), + (48.27074009522731, 37.509029159545906), + (48.263312668696855, 37.51207614898682), + (48.26539817051818, 37.50087524414063), + (48.25851283439989, 37.49452377319337), + (48.254426906081555, 37.509801635742195), + (48.25914140977405, 37.52568031311036), + (48.25354110233028, 37.536752471923835), + (48.25902712391726, 37.551257858276374), + (48.26828345053738, 37.537009963989265), + (48.27421563182974, 37.52345758819581), + (48.26889854647051, 37.513029159545906), + (48.26147111993905, 37.51607614898682), + (48.26355662176038, 37.50487524414063), + (48.25667128564209, 37.49852377319337), + (48.25258535732375, 37.513801635742195), + (48.25729986101625, 37.52968031311036), + (48.25169955357248, 37.540752471923835), + (48.25718557515946, 37.555257858276374), + (48.26644190177958, 37.541009963989265), + }; + } +} diff --git a/SatelliteProvider.Tests/GoogleMapsDownloaderTests.cs b/SatelliteProvider.Tests/GoogleMapsDownloaderTests.cs deleted file mode 100644 index b46fd00..0000000 --- a/SatelliteProvider.Tests/GoogleMapsDownloaderTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentAssertions; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using SatelliteProvider.Common.Configs; -using SatelliteProvider.Common.DTO; -using SatelliteProvider.Services; -using Xunit; - -namespace SatelliteProvider.Tests; - -public class DummyTests -{ - [Fact] - public void Dummy_ShouldWork() - { - Assert.Equal(1, 1); - } -} diff --git a/SatelliteProvider.Tests/InfrastructureTests.cs b/SatelliteProvider.Tests/InfrastructureTests.cs new file mode 100644 index 0000000..ee92abb --- /dev/null +++ b/SatelliteProvider.Tests/InfrastructureTests.cs @@ -0,0 +1,71 @@ +using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using SatelliteProvider.Common.DTO; +using SatelliteProvider.Common.Interfaces; +using SatelliteProvider.DataAccess.Models; +using SatelliteProvider.DataAccess.Repositories; +using SatelliteProvider.Services; +using SatelliteProvider.Tests.Fixtures; + +namespace SatelliteProvider.Tests; + +public class InfrastructureTests +{ + [Fact] + public void AllMockableInterfaces_CanBeMocked() + { + // Arrange + Act + var downloader = new Mock(); + var tileRepo = new Mock(); + var regionRepo = new Mock(); + var routeRepo = new Mock(); + var queue = new Mock(); + var tileService = new Mock(); + var regionService = new Mock(); + var routeService = new Mock(); + + // Assert + downloader.Object.Should().NotBeNull(); + tileRepo.Object.Should().NotBeNull(); + regionRepo.Object.Should().NotBeNull(); + routeRepo.Object.Should().NotBeNull(); + queue.Object.Should().NotBeNull(); + tileService.Object.Should().NotBeNull(); + regionService.Object.Should().NotBeNull(); + routeService.Object.Should().NotBeNull(); + } + + [Fact] + public void TestCoordinates_TileCenter_MatchesPrimaryTilePoint() + { + // Assert + TestCoordinates.TileCenter.Lat.Should().Be(47.461747); + TestCoordinates.TileCenter.Lon.Should().Be(37.647063); + TestCoordinates.DefaultZoom.Should().Be(18); + } + + [Fact] + public void TestCoordinates_RoutePoints_HaveExpectedCounts() + { + // Assert + TestCoordinates.Route.Route01Points.Should().HaveCount(2); + TestCoordinates.Route.Route04Points.Should().HaveCount(10); + TestCoordinates.Route.Route06Points.Should().HaveCount(20); + } + + [Fact] + public void TileService_ConstructsWithMockedDependencies() + { + // Arrange + var downloader = new Mock().Object; + var tileRepo = new Mock().Object; + var logger = NullLogger.Instance; + + // Act + var service = new TileService(downloader, tileRepo, logger); + + // Assert + service.Should().NotBeNull(); + } +} diff --git a/SatelliteProvider.Tests/SatelliteProvider.Tests.csproj b/SatelliteProvider.Tests/SatelliteProvider.Tests.csproj index 986019d..ebecbd8 100644 --- a/SatelliteProvider.Tests/SatelliteProvider.Tests.csproj +++ b/SatelliteProvider.Tests/SatelliteProvider.Tests.csproj @@ -37,6 +37,7 @@ + diff --git a/_docs/02_tasks/todo/AZ-285_test_infrastructure.md b/_docs/02_tasks/done/AZ-285_test_infrastructure.md similarity index 100% rename from _docs/02_tasks/todo/AZ-285_test_infrastructure.md rename to _docs/02_tasks/done/AZ-285_test_infrastructure.md diff --git a/_docs/03_implementation/reviews/batch_01_review.md b/_docs/03_implementation/reviews/batch_01_review.md new file mode 100644 index 0000000..cbd4749 --- /dev/null +++ b/_docs/03_implementation/reviews/batch_01_review.md @@ -0,0 +1,49 @@ +# Code Review Report + +**Batch**: 1 — AZ-285 Test Infrastructure +**Date**: 2026-05-10 +**Verdict**: PASS_WITH_WARNINGS + +## Findings + +| # | Severity | Category | File:Line | Title | +|---|----------|----------|-----------|-------| +| 1 | Low | Spec-Gap | (deferred) | AC-2 (docker-compose tests succeed) deferred to Step 7 | +| 2 | Low | Maintainability | SatelliteProvider.Tests/SatelliteProvider.Tests.csproj | FluentAssertions 8.x licensing — pre-existing, surfaces in test output | + +### Finding Details + +**F1: AC-2 deferred to Step 7** (Low / Spec-Gap) +- Location: out-of-batch +- Description: AZ-285 AC-2 requires `docker-compose -f docker-compose.yml -f docker-compose.tests.yml up --build --abort-on-container-exit` to succeed. This batch only validates the unit test path via a plain `mcr.microsoft.com/dotnet/sdk:8.0` container. The full compose stack runs against the API + Postgres in Step 7 (Run Tests). +- Suggestion: Verify in Step 7 by running `scripts/run-tests.sh` (the full path). +- Task: AZ-285 + +**F2: FluentAssertions 8.x commercial-use license** (Low / Maintainability) +- Location: `SatelliteProvider.Tests/SatelliteProvider.Tests.csproj` +- Description: FluentAssertions 8.x was relicensed under Xceed Community License — free for non-commercial use only. The test runner emits this notice. Version was set pre-autodev; this batch did not introduce it. +- Suggestion: For commercial-use projects, downgrade to FluentAssertions 7.x or migrate to Shouldly / Verify. Decision belongs to the user (not in scope for AZ-285). +- Task: pre-existing + +## Phase Summary + +- **Phase 1 (Context)**: AZ-285 spec loaded, ACs identified. +- **Phase 2 (Spec compliance)**: AC-1 ✓ (project builds, mocks resolve — verified by `AllMockableInterfaces_CanBeMocked` + `TileService_ConstructsWithMockedDependencies`); AC-3 ✓ (4 tests discovered + executed); AC-2 deferred (F1). +- **Phase 3 (Quality)**: simple, focused fixtures and smoke tests; no SOLID violations. +- **Phase 4 (Security)**: no secrets, no injection vectors in test code. +- **Phase 5 (Performance)**: N/A for test infrastructure. +- **Phase 6 (Cross-task)**: single task in batch. +- **Phase 7 (Architecture)**: test project's references (Common, Services, DataAccess) all hit Public APIs; no layering violation; no new cycles. + +## Test Run + +Container: `mcr.microsoft.com/dotnet/sdk:8.0` +- Restored: 4 projects +- Built: 4 projects (Common, DataAccess, Services, Tests) +- Tests discovered: 4 +- Passed: 4 / 4 +- Total time: 2.35s + +## Verdict Logic + +No Critical or High findings → PASS_WITH_WARNINGS. diff --git a/_docs/_autodev_state.md b/_docs/_autodev_state.md index 5faa92c..8ceee3f 100644 --- a/_docs/_autodev_state.md +++ b/_docs/_autodev_state.md @@ -6,8 +6,9 @@ step: 6 name: Implement Tests status: in_progress sub_step: - phase: 0 - name: awaiting-invocation - detail: "" + phase: 6 + name: batch-loop + detail: "batch 1 of 3 — AZ-285 test infrastructure" retry_count: 0 cycle: 1 +tracker: jira