#0040 增加测试用例

This commit is contained in:
zhengxuan.zhang
2026-03-18 20:41:05 +08:00
parent 67898edc3f
commit 180501808e
8 changed files with 121 additions and 1621 deletions
@@ -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&lt;RecipeGenerators&gt;() 注册。
/// 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;
}
}
}
}