mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 23:11:14 +00:00
[AZ-285] Test infrastructure: scaffold unit test project + fixtures
- Add SatelliteProvider.DataAccess project reference to test csproj
(enables mocking ITileRepository / IRegionRepository / IRouteRepository)
- Replace DummyTest placeholder with InfrastructureTests covering:
* All mockable interfaces (ISatelliteDownloader, repos, queue, services)
can be mocked via Moq
* TileService can be constructed with mocked dependencies
* Test coordinate fixtures load with expected values
- Add Fixtures/TestCoordinates.cs with REG-01..REG-03 + ROUTE-01/04/06
shared test data
- Archive AZ-285 to _docs/02_tasks/done/
- Batch 1 review report: PASS_WITH_WARNINGS (Low/Spec-Gap deferred AC-2,
Low/Maintainability pre-existing FluentAssertions 8.x license note)
Verification: docker dotnet test run — 4/4 tests pass in 2.35s.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<ISatelliteDownloader>();
|
||||
var tileRepo = new Mock<ITileRepository>();
|
||||
var regionRepo = new Mock<IRegionRepository>();
|
||||
var routeRepo = new Mock<IRouteRepository>();
|
||||
var queue = new Mock<IRegionRequestQueue>();
|
||||
var tileService = new Mock<ITileService>();
|
||||
var regionService = new Mock<IRegionService>();
|
||||
var routeService = new Mock<IRouteService>();
|
||||
|
||||
// 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<ISatelliteDownloader>().Object;
|
||||
var tileRepo = new Mock<ITileRepository>().Object;
|
||||
var logger = NullLogger<TileService>.Instance;
|
||||
|
||||
// Act
|
||||
var service = new TileService(downloader, tileRepo, logger);
|
||||
|
||||
// Assert
|
||||
service.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SatelliteProvider.Services\SatelliteProvider.Services.csproj" />
|
||||
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
||||
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user