#0040 增加测试用例
This commit is contained in:
@@ -2,23 +2,21 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FsCheck;
|
||||
using FsCheck.Fluent;
|
||||
using XplorePlane.Models;
|
||||
|
||||
namespace XplorePlane.Tests.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// FsCheck 自定义生成器:为配方相关模型定义 Arbitrary 生成器。
|
||||
/// 使用 Arb.Register<RecipeGenerators>() 注册。
|
||||
/// FsCheck 3.x 自定义生成器:为配方相关模型定义 Arbitrary 生成器。
|
||||
/// </summary>
|
||||
public class RecipeGenerators
|
||||
{
|
||||
// ── PipelineModel: class with settable properties ──
|
||||
|
||||
public static Arbitrary<PipelineModel> PipelineModelArb()
|
||||
{
|
||||
var gen = from id in Arb.Default.Guid().Generator
|
||||
from name in Arb.Default.NonEmptyString().Generator
|
||||
from deviceId in Arb.Default.NonEmptyString().Generator
|
||||
var gen = from id in ArbMap.Default.GeneratorFor<Guid>()
|
||||
from name in ArbMap.Default.GeneratorFor<NonEmptyString>()
|
||||
from deviceId in ArbMap.Default.GeneratorFor<NonEmptyString>()
|
||||
from ticks in Gen.Choose(0, int.MaxValue)
|
||||
let createdAt = DateTime.MinValue.AddTicks((long)ticks * 10000)
|
||||
let updatedAt = createdAt
|
||||
@@ -31,11 +29,9 @@ namespace XplorePlane.Tests.Generators
|
||||
UpdatedAt = updatedAt,
|
||||
Nodes = new List<PipelineNodeModel>()
|
||||
};
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── RecipeStep: reuses StateGenerators for hardware states ──
|
||||
|
||||
public static Arbitrary<RecipeStep> RecipeStepArb()
|
||||
{
|
||||
var gen = from stepIndex in Gen.Choose(0, 100)
|
||||
@@ -44,15 +40,13 @@ namespace XplorePlane.Tests.Generators
|
||||
from detector in StateGenerators.DetectorStateArb().Generator
|
||||
from pipeline in PipelineModelArb().Generator
|
||||
select new RecipeStep(stepIndex, motion, ray, detector, pipeline);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── InspectionRecipe: 0-10 steps with sequential StepIndex ──
|
||||
|
||||
public static Arbitrary<InspectionRecipe> InspectionRecipeArb()
|
||||
{
|
||||
var gen = from id in Arb.Default.Guid().Generator
|
||||
from name in Arb.Default.NonEmptyString().Generator
|
||||
var gen = from id in ArbMap.Default.GeneratorFor<Guid>()
|
||||
from name in ArbMap.Default.GeneratorFor<NonEmptyString>()
|
||||
from ticks in Gen.Choose(0, int.MaxValue)
|
||||
let createdAt = DateTime.MinValue.AddTicks((long)ticks * 10000)
|
||||
let updatedAt = createdAt
|
||||
@@ -64,11 +58,9 @@ namespace XplorePlane.Tests.Generators
|
||||
createdAt,
|
||||
updatedAt,
|
||||
steps.AsReadOnly());
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── RecipeExecutionState ──
|
||||
|
||||
public static Arbitrary<RecipeExecutionState> RecipeExecutionStateArb()
|
||||
{
|
||||
var gen = from totalSteps in Gen.Choose(0, 50)
|
||||
@@ -79,27 +71,32 @@ namespace XplorePlane.Tests.Generators
|
||||
RecipeExecutionStatus.Paused,
|
||||
RecipeExecutionStatus.Completed,
|
||||
RecipeExecutionStatus.Error)
|
||||
from recipeName in Arb.Default.NonEmptyString().Generator
|
||||
from recipeName in ArbMap.Default.GeneratorFor<NonEmptyString>()
|
||||
select new RecipeExecutionState(currentStep, totalSteps, status, recipeName.Get);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── Helper: generate a list of steps with sequential StepIndex 0..n-1 ──
|
||||
|
||||
private static Gen<List<RecipeStep>> GenSequentialSteps(int count)
|
||||
{
|
||||
if (count == 0)
|
||||
return Gen.Constant(new List<RecipeStep>());
|
||||
|
||||
return Gen.Sequence(
|
||||
Enumerable.Range(0, count).Select(i =>
|
||||
from motion in StateGenerators.MotionStateArb().Generator
|
||||
from ray in StateGenerators.RaySourceStateArb().Generator
|
||||
from detector in StateGenerators.DetectorStateArb().Generator
|
||||
from pipeline in PipelineModelArb().Generator
|
||||
select new RecipeStep(i, motion, ray, detector, pipeline)
|
||||
)
|
||||
).Select(steps => steps.ToList());
|
||||
// Build list step by step using SelectMany chain
|
||||
Gen<List<RecipeStep>> result = Gen.Constant(new List<RecipeStep>());
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var idx = i;
|
||||
result = from list in result
|
||||
from motion in StateGenerators.MotionStateArb().Generator
|
||||
from ray in StateGenerators.RaySourceStateArb().Generator
|
||||
from detector in StateGenerators.DetectorStateArb().Generator
|
||||
from pipeline in PipelineModelArb().Generator
|
||||
select new List<RecipeStep>(list)
|
||||
{
|
||||
new RecipeStep(idx, motion, ray, detector, pipeline)
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
using System;
|
||||
using FsCheck;
|
||||
using FsCheck.Fluent;
|
||||
using XplorePlane.Models;
|
||||
|
||||
namespace XplorePlane.Tests.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// FsCheck 自定义生成器:为所有状态模型定义 Arbitrary 生成器。
|
||||
/// 使用 Arb.Register<StateGenerators>() 注册。
|
||||
/// FsCheck 3.x 自定义生成器:为所有状态模型定义 Arbitrary 生成器。
|
||||
/// </summary>
|
||||
public class StateGenerators
|
||||
{
|
||||
// ── 位置范围: -10000 ~ 10000, 速度范围: 0 ~ 1000 ──
|
||||
|
||||
private static Gen<double> PositionGen =>
|
||||
Gen.Choose(-10000000, 10000000).Select(i => i / 1000.0);
|
||||
|
||||
@@ -30,8 +28,6 @@ namespace XplorePlane.Tests.Generators
|
||||
private static Gen<double> MatrixGen =>
|
||||
Gen.Choose(-10000000, 10000000).Select(i => i / 1000.0);
|
||||
|
||||
// ── MotionState: 6 positions + 6 speeds ──
|
||||
|
||||
public static Arbitrary<MotionState> MotionStateArb()
|
||||
{
|
||||
var gen = from xm in PositionGen
|
||||
@@ -48,34 +44,28 @@ namespace XplorePlane.Tests.Generators
|
||||
from distSpd in SpeedGen
|
||||
select new MotionState(xm, ym, zt, zd, tiltD, dist,
|
||||
xmSpd, ymSpd, ztSpd, zdSpd, tiltDSpd, distSpd);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── RaySourceState: bool + 2 doubles ──
|
||||
|
||||
public static Arbitrary<RaySourceState> RaySourceStateArb()
|
||||
{
|
||||
var gen = from isOn in Arb.Default.Bool().Generator
|
||||
var gen = from isOn in ArbMap.Default.GeneratorFor<bool>()
|
||||
from voltage in VoltageGen
|
||||
from power in PowerGen
|
||||
select new RaySourceState(isOn, voltage, power);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── DetectorState: 2 bools + double + string ──
|
||||
|
||||
public static Arbitrary<DetectorState> DetectorStateArb()
|
||||
{
|
||||
var gen = from isConnected in Arb.Default.Bool().Generator
|
||||
from isAcquiring in Arb.Default.Bool().Generator
|
||||
var gen = from isConnected in ArbMap.Default.GeneratorFor<bool>()
|
||||
from isAcquiring in ArbMap.Default.GeneratorFor<bool>()
|
||||
from frameRate in FrameRateGen
|
||||
from res in Gen.Elements("1024x1024", "2048x2048", "2880x2880", "3072x3072", "4260x4260")
|
||||
select new DetectorState(isConnected, isAcquiring, frameRate, res);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── SystemState: OperationMode enum + bool + string ──
|
||||
|
||||
public static Arbitrary<SystemState> SystemStateArb()
|
||||
{
|
||||
var gen = from mode in Gen.Elements(
|
||||
@@ -83,28 +73,24 @@ namespace XplorePlane.Tests.Generators
|
||||
OperationMode.Scanning,
|
||||
OperationMode.CTAcquire,
|
||||
OperationMode.RecipeRun)
|
||||
from hasError in Arb.Default.Bool().Generator
|
||||
from msg in Arb.Default.NonEmptyString().Generator
|
||||
from hasError in ArbMap.Default.GeneratorFor<bool>()
|
||||
from msg in ArbMap.Default.GeneratorFor<NonEmptyString>()
|
||||
let errorMessage = hasError ? msg.Get : string.Empty
|
||||
select new SystemState(mode, hasError, errorMessage);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── CameraState: 2 bools + null CurrentFrame + 2 ints + double ──
|
||||
|
||||
public static Arbitrary<CameraState> CameraStateArb()
|
||||
{
|
||||
var gen = from isConnected in Arb.Default.Bool().Generator
|
||||
from isStreaming in Arb.Default.Bool().Generator
|
||||
var gen = from isConnected in ArbMap.Default.GeneratorFor<bool>()
|
||||
from isStreaming in ArbMap.Default.GeneratorFor<bool>()
|
||||
from width in Gen.Choose(0, 8192)
|
||||
from height in Gen.Choose(0, 8192)
|
||||
from frameRate in FrameRateGen
|
||||
select new CameraState(isConnected, isStreaming, null, width, height, frameRate);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── CalibrationMatrix: 9 doubles ──
|
||||
|
||||
public static Arbitrary<CalibrationMatrix> CalibrationMatrixArb()
|
||||
{
|
||||
var gen = from m11 in MatrixGen
|
||||
@@ -117,30 +103,26 @@ namespace XplorePlane.Tests.Generators
|
||||
from m32 in MatrixGen
|
||||
from m33 in MatrixGen
|
||||
select new CalibrationMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── PhysicalPosition: 3 doubles ──
|
||||
|
||||
public static Arbitrary<PhysicalPosition> PhysicalPositionArb()
|
||||
{
|
||||
var gen = from x in PositionGen
|
||||
from y in PositionGen
|
||||
from z in PositionGen
|
||||
select new PhysicalPosition(x, y, z);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
|
||||
// ── LinkedViewState: PhysicalPosition + bool + DateTime ──
|
||||
|
||||
public static Arbitrary<LinkedViewState> LinkedViewStateArb()
|
||||
{
|
||||
var gen = from pos in PhysicalPositionArb().Generator
|
||||
from isExecuting in Arb.Default.Bool().Generator
|
||||
from isExecuting in ArbMap.Default.GeneratorFor<bool>()
|
||||
from ticks in Gen.Choose(0, int.MaxValue)
|
||||
let dt = DateTime.MinValue.AddTicks((long)ticks * 10000)
|
||||
select new LinkedViewState(pos, isExecuting, dt);
|
||||
return Arb.From(gen);
|
||||
return gen.ToArbitrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user