Files
I150/srcs/RobotNet10/Tests/RobotNet10.NavigationTune.Test/Execution/TuningNavigationTests.cs
2026-07-03 16:37:12 +07:00

271 lines
8.3 KiB
C#

using FluentAssertions;
using Moq;
using Xunit;
using RobotNet10.NavigationTune.Execution;
using RobotNet10.NavigationTune.Shared.Interfaces;
using RobotNet10.NavigationTune.Shared.Models;
using RobotNet10.NavigationTune.Test.Helpers;
using RobotNet10.NavigationTune.Services;
namespace RobotNet10.NavigationTune.Test.Execution;
public class TuningNavigationTests
{
private Mock<ITestExecutor> CreateMockTestExecutor()
{
var mock = new Mock<ITestExecutor>();
return mock;
}
private Mock<IMetricsCalculator> CreateMockMetricsCalculator()
{
var mock = new Mock<IMetricsCalculator>();
mock.Setup(m => m.CalculateMetrics(
It.IsAny<List<TelemetryData>>(),
It.IsAny<ReferencePath>()))
.Returns(new TestMetrics
{
OverallScore = 0.85f,
CrossTrackErrorRMS = 0.05f,
HeadingErrorRMS = 0.02f
});
return mock;
}
[Fact]
public void Constructor_WithDependencies_ShouldInitialize()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
// Act
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Assert
tuningNav.Should().NotBeNull();
tuningNav.IsTestRunning.Should().BeFalse();
}
[Fact]
public async Task ExecuteTestAsync_WithValidInputs_ShouldReturnResult()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
testExecutor.Setup(e => e.ExecuteAsync(
It.IsAny<TestScenario>(),
It.IsAny<NavigationParameterSet>(),
It.IsAny<Action<TelemetryData>>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(new TestExecutionResult
{
TestRunId = Guid.NewGuid(),
Status = TestStatus.Completed,
TelemetryData = new List<TelemetryData>(),
StartTime = DateTime.UtcNow
});
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
var scenario = TestHelpers.CreateStraightLineScenario();
var parameters = TestHelpers.CreateDefaultParameterSet();
// Act
var result = await tuningNav.ExecuteTestAsync(scenario, parameters);
// Assert
result.Should().NotBeNull();
result.Status.Should().Be(TestStatus.Completed);
testExecutor.Verify(e => e.ExecuteAsync(
It.IsAny<TestScenario>(),
It.IsAny<NavigationParameterSet>(),
It.IsAny<Action<TelemetryData>>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task ExecuteTestAsync_WhenAlreadyRunning_ShouldThrow()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
// Simulate long-running test
testExecutor.Setup(e => e.ExecuteAsync(
It.IsAny<TestScenario>(),
It.IsAny<NavigationParameterSet>(),
It.IsAny<Action<TelemetryData>>(),
It.IsAny<CancellationToken>()))
.Returns(async () =>
{
await Task.Delay(1000);
return new TestExecutionResult { Status = TestStatus.Completed };
});
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
var scenario = TestHelpers.CreateStraightLineScenario();
var parameters = TestHelpers.CreateDefaultParameterSet();
// Act
var task1 = tuningNav.ExecuteTestAsync(scenario, parameters);
await Task.Delay(50); // Let first test start
// Assert
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
await tuningNav.ExecuteTestAsync(scenario, parameters));
// Cleanup
tuningNav.Stop();
await task1;
}
[Fact]
public void GetProgress_ShouldDelegateToTestExecutor()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
testExecutor.Setup(e => e.GetProgress())
.Returns(new TestProgress
{
ProgressPercent = 0.5,
DistanceTraveled = 5.0
});
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Act
var progress = tuningNav.GetProgress();
// Assert
progress.Should().NotBeNull();
progress.ProgressPercent.Should().Be(0.5);
testExecutor.Verify(e => e.GetProgress(), Times.Once);
}
[Fact]
public void Pause_ShouldDelegateToTestExecutor()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Act
tuningNav.Pause();
// Assert
testExecutor.Verify(e => e.Pause(), Times.Once);
}
[Fact]
public void Resume_ShouldDelegateToTestExecutor()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Act
tuningNav.Resume();
// Assert
testExecutor.Verify(e => e.Resume(), Times.Once);
}
[Fact]
public void Stop_ShouldDelegateToTestExecutor()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Act
tuningNav.Stop();
// Assert
testExecutor.Verify(e => e.Stop(), Times.Once);
}
[Fact]
public void EmergencyStop_ShouldDelegateToTestExecutor()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
// Act
tuningNav.EmergencyStop();
// Assert
testExecutor.Verify(e => e.EmergencyStop(), Times.Once);
}
[Fact]
public async Task ExecuteTestAsync_ShouldInvokeTelemetryUpdateEvent()
{
// Arrange
var testExecutor = CreateMockTestExecutor();
var metricsCalculator = CreateMockMetricsCalculator();
var telemetryReceived = false;
var tuningNav = new TuningNavigation(
testExecutor.Object,
metricsCalculator.Object);
tuningNav.OnTelemetryUpdate += (telemetry) => telemetryReceived = true;
testExecutor.Setup(e => e.ExecuteAsync(
It.IsAny<TestScenario>(),
It.IsAny<NavigationParameterSet>(),
It.IsAny<Action<TelemetryData>>(),
It.IsAny<CancellationToken>()))
.Callback<TestScenario, NavigationParameterSet, Action<TelemetryData>?, CancellationToken>(
(s, p, callback, ct) =>
{
callback?.Invoke(TestHelpers.CreateTelemetryData());
})
.ReturnsAsync(new TestExecutionResult
{
Status = TestStatus.Completed,
TelemetryData = new List<TelemetryData>()
});
var scenario = TestHelpers.CreateStraightLineScenario();
var parameters = TestHelpers.CreateDefaultParameterSet();
// Act
await tuningNav.ExecuteTestAsync(scenario, parameters);
// Assert
telemetryReceived.Should().BeTrue();
}
}