#0021 增加测试工程
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using XplorePlane.Models;
|
||||
using XplorePlane.Services;
|
||||
using XplorePlane.ViewModels;
|
||||
using XplorePlane.Tests.Helpers;
|
||||
|
||||
namespace XplorePlane.Tests.Pipeline
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试 PipelineEditorViewModel 的命令逻辑
|
||||
/// 覆盖任务 6.1 / 6.2 / 6.3 / 6.4 / 6.8
|
||||
/// </summary>
|
||||
public class PipelineEditorViewModelTests
|
||||
{
|
||||
private readonly Mock<IImageProcessingService> _mockImageSvc;
|
||||
private readonly Mock<IPipelineExecutionService> _mockExecSvc;
|
||||
private readonly Mock<IPipelinePersistenceService> _mockPersistSvc;
|
||||
|
||||
public PipelineEditorViewModelTests()
|
||||
{
|
||||
_mockImageSvc = TestHelpers.CreateMockImageService();
|
||||
_mockExecSvc = new Mock<IPipelineExecutionService>();
|
||||
_mockPersistSvc = new Mock<IPipelinePersistenceService>();
|
||||
}
|
||||
|
||||
private PipelineEditorViewModel CreateVm() =>
|
||||
new PipelineEditorViewModel(_mockImageSvc.Object, _mockExecSvc.Object, _mockPersistSvc.Object);
|
||||
|
||||
// ── 6.1 AddOperatorCommand ────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void AddOperator_ValidKey_AppendsNode()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
|
||||
Assert.Single(vm.PipelineNodes);
|
||||
Assert.Equal("Blur", vm.PipelineNodes[0].OperatorKey);
|
||||
Assert.Equal(0, vm.PipelineNodes[0].Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddOperator_InvalidKey_NodeNotAdded()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("NonExistentKey");
|
||||
|
||||
Assert.Empty(vm.PipelineNodes);
|
||||
Assert.Contains("未注册", vm.StatusMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddOperator_NullKey_NodeNotAdded()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute(null);
|
||||
|
||||
Assert.Empty(vm.PipelineNodes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddOperator_ExceedsMaxLength_NodeNotAdded()
|
||||
{
|
||||
// 主项目中 MaxPipelineLength = 20,通过反射读取或直接添加 20 个
|
||||
var vm = CreateVm();
|
||||
for (int i = 0; i < 20; i++)
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
|
||||
Assert.Equal(20, vm.PipelineNodes.Count);
|
||||
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
|
||||
Assert.Equal(20, vm.PipelineNodes.Count);
|
||||
Assert.Contains("上限", vm.StatusMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddOperator_MultipleNodes_OrderIsSequential()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
vm.AddOperatorCommand.Execute("Sharpen");
|
||||
vm.AddOperatorCommand.Execute("Threshold");
|
||||
|
||||
Assert.Equal(3, vm.PipelineNodes.Count);
|
||||
for (int i = 0; i < 3; i++)
|
||||
Assert.Equal(i, vm.PipelineNodes[i].Order);
|
||||
}
|
||||
|
||||
// ── 6.2 RemoveOperatorCommand ─────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void RemoveOperator_ExistingNode_NodeRemoved()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
var node = vm.PipelineNodes[0];
|
||||
|
||||
vm.RemoveOperatorCommand.Execute(node);
|
||||
|
||||
Assert.Empty(vm.PipelineNodes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveOperator_MiddleNode_OrderRenumbered()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
vm.AddOperatorCommand.Execute("Sharpen");
|
||||
vm.AddOperatorCommand.Execute("Threshold");
|
||||
var middle = vm.PipelineNodes[1];
|
||||
|
||||
vm.RemoveOperatorCommand.Execute(middle);
|
||||
|
||||
Assert.Equal(2, vm.PipelineNodes.Count);
|
||||
Assert.Equal(0, vm.PipelineNodes[0].Order);
|
||||
Assert.Equal(1, vm.PipelineNodes[1].Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveOperator_SelectedNode_SelectedNodeCleared()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
var node = vm.PipelineNodes[0];
|
||||
vm.SelectedNode = node;
|
||||
|
||||
vm.RemoveOperatorCommand.Execute(node);
|
||||
|
||||
Assert.Null(vm.SelectedNode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveOperator_NullNode_NoException()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
var ex = Record.Exception(() => vm.RemoveOperatorCommand.Execute(null));
|
||||
Assert.Null(ex);
|
||||
}
|
||||
|
||||
// ── 6.3 ReorderOperatorCommand ────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void ReorderOperator_MoveFirstToLast_OrderConsistent()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
vm.AddOperatorCommand.Execute("Sharpen");
|
||||
vm.AddOperatorCommand.Execute("Threshold");
|
||||
|
||||
vm.ReorderOperatorCommand.Execute(new PipelineReorderArgs { OldIndex = 0, NewIndex = 2 });
|
||||
|
||||
for (int i = 0; i < vm.PipelineNodes.Count; i++)
|
||||
Assert.Equal(i, vm.PipelineNodes[i].Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReorderOperator_MoveLastToFirst_OrderConsistent()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
vm.AddOperatorCommand.Execute("Sharpen");
|
||||
vm.AddOperatorCommand.Execute("Threshold");
|
||||
var lastName = vm.PipelineNodes[2].OperatorKey;
|
||||
|
||||
vm.ReorderOperatorCommand.Execute(new PipelineReorderArgs { OldIndex = 2, NewIndex = 0 });
|
||||
|
||||
Assert.Equal(lastName, vm.PipelineNodes[0].OperatorKey);
|
||||
for (int i = 0; i < vm.PipelineNodes.Count; i++)
|
||||
Assert.Equal(i, vm.PipelineNodes[i].Order);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReorderOperator_SameIndex_NoChange()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
vm.AddOperatorCommand.Execute("Sharpen");
|
||||
var originalFirst = vm.PipelineNodes[0].OperatorKey;
|
||||
|
||||
vm.ReorderOperatorCommand.Execute(new PipelineReorderArgs { OldIndex = 0, NewIndex = 0 });
|
||||
|
||||
Assert.Equal(originalFirst, vm.PipelineNodes[0].OperatorKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReorderOperator_OutOfBoundsIndex_NoException()
|
||||
{
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
|
||||
var ex = Record.Exception(() =>
|
||||
vm.ReorderOperatorCommand.Execute(new PipelineReorderArgs { OldIndex = 0, NewIndex = 99 }));
|
||||
Assert.Null(ex);
|
||||
}
|
||||
|
||||
// ── 6.4 LoadNodeParameters ────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void LoadNodeParameters_ModifiedValuePreserved()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 20);
|
||||
_mockImageSvc.Setup(s => s.GetProcessorParameters("Blur"))
|
||||
.Returns(new[] { param });
|
||||
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
var node = vm.PipelineNodes[0];
|
||||
|
||||
// 修改参数值
|
||||
node.Parameters[0].Value = 10;
|
||||
|
||||
// 重新选中节点触发 LoadNodeParameters
|
||||
vm.SelectedNode = null;
|
||||
vm.SelectedNode = node;
|
||||
|
||||
Assert.Equal(10, node.Parameters[0].Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadNodeParameters_UnmodifiedUsesDefault()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 20);
|
||||
_mockImageSvc.Setup(s => s.GetProcessorParameters("Blur"))
|
||||
.Returns(new[] { param });
|
||||
|
||||
var vm = CreateVm();
|
||||
vm.AddOperatorCommand.Execute("Blur");
|
||||
var node = vm.PipelineNodes[0];
|
||||
|
||||
Assert.Equal(5, node.Parameters[0].Value);
|
||||
}
|
||||
|
||||
// ── 6.8 参数范围校验 ──────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void ParameterValidation_ValueWithinRange_IsValid()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 10);
|
||||
var vm = new ProcessorParameterVM(param) { Value = 7 };
|
||||
|
||||
Assert.True(vm.IsValueValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterValidation_ValueBelowMin_IsInvalid()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 10);
|
||||
var vm = new ProcessorParameterVM(param) { Value = 0 };
|
||||
|
||||
Assert.False(vm.IsValueValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterValidation_ValueAboveMax_IsInvalid()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 10);
|
||||
var vm = new ProcessorParameterVM(param) { Value = 11 };
|
||||
|
||||
Assert.False(vm.IsValueValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterValidation_BoundaryValues_AreValid()
|
||||
{
|
||||
var param = TestHelpers.MakeIntParam("Radius", value: 5, min: 1, max: 10);
|
||||
var vmMin = new ProcessorParameterVM(param) { Value = 1 };
|
||||
var vmMax = new ProcessorParameterVM(param) { Value = 10 };
|
||||
|
||||
Assert.True(vmMin.IsValueValid);
|
||||
Assert.True(vmMax.IsValueValid);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user