C#中的FsCheck:生成具有相同形状的二维数组的列表
假设我正在编写一些视频分析代码。这里是一个视频类的简化版本:C#中的FsCheck:生成具有相同形状的二维数组的列表
public class Video
{
public readonly int Width;
public readonly int Height;
public readonly List<int[,]> Frames;
public Video(int width, int height, IEnumerable<int[,]> frames)
{
Width = width;
Height = height;
Frames = new List<int[,]>();
foreach (var frame in frames)
{
if (frame.GetLength(0) != height || frame.GetLength(1) != width)
{
throw new ArgumentException("Incorrect frames dimensions");
}
Frames.Add(frame);
}
}
}
如何使一个Arbitrary<Video>
并注册了吗?我如何为这个任意做一个收缩器?
试过,不明白如何应用工程:
public static Arbitrary<Video> Videos()
{
var videoGen = Arb.Generate<PositiveInt>()
.SelectMany(w => Arb.Generate<PositiveInt>(), (w, h) => new {w, h})
.Apply(/* what is Gen<Func<a,b>> */);
return videoGen.ToArbitrary();
}
想这一点,但在这里不能堵塞发电机清单:
public static Arbitrary<Video> Videos()
{
var videoGen = Arb.Generate<PositiveInt>()
.SelectMany(w => Arb.Generate<PositiveInt>(), (w, h) => new Video(w, h, /* how to plug generator here? */));
return videoGen.ToArbitrary();
}
以库尔特Schelfthout的答案为基础,你可以写一个任意的fo r是video
类是这样的:
public static class VideoArbitrary
{
public static Arbitrary<Video> Videos()
{
var genVideo = from w in Arb.Generate<PositiveInt>()
from h in Arb.Generate<PositiveInt>()
from arrs in Gen.ListOf(
Gen.Array2DOf<int>(
h.Item,
w.Item,
Arb.Generate<int>()))
select new Video(w.Item, h.Item, arrs);
return genVideo.ToArbitrary();
}
}
您可以以不同的方式使用它。
普通的香草FsCheck
以下是如何与普通的香草FsCheck,一个xUnit.net测试用例内这里举办,这是不需要使用视频武断,你可以在你喜欢的任何过程举办这样的:
[Fact]
public void VideoProperty()
{
var property = Prop.ForAll(
VideoArbitrary.Videos(),
video =>
{
// Test goes here...
Assert.NotNull(video);
});
property.QuickCheckThrowOnFailure();
}
Prop.ForAll
对于用自定义仲裁来定义属性非常有用。当您致电QuickCheckThrowOnFailure
时,它将运行Video
类的“全部”(通过defailt:100)值的测试。
非类型化xUnit.net财产
您也可以使用FsCheck.Xunit胶图书馆,但你必须要通过任意一个弱类型值属性:
[Property(Arbitrary = new[] { typeof(VideoArbitrary) })]
public void XunitPropertyWithWeaklyTypedArbitrary(Video video)
{
// Test goes here...
Assert.NotNull(video);
}
这很简单并且容易理解,但在分配Arbitrary
属性时没有涉及静态类型检查,所以我不太喜欢这种方法。
类型化xUnit.net财产
一种更好的方式来使用FsCheck.Xunit定制Arbitraries是combine it with Prop.ForAll:
[Property]
public Property XUnitPropertyWithStronglyTypedArbitrary()
{
return Prop.ForAll(
VideoArbitrary.Videos(),
video =>
{
// Test goes here...
Assert.NotNull(video);
});
}
注意,这个方法的返回类型不再void
,但Property
; [Property]
属性理解此类型并相应地执行测试。
第三个选项是我在xUnit.net中使用自定义仲裁的首选方式,因为它会带来编译时检查。
就在一时冲动草图 - 未编译:)
var genVideo = from w in Arb.Generate<PositiveInt>()
from h in Arb.Generate<PositiveInt>()
from arrs in Gen.ListOf(Gen.Array2DOf(h, w, Arb.Generate<int>))
select new Video(w, h, arrs);
这给了我一个很好的开始,但在编译之前我必须稍微摆动一下:) –
我不知道键入的xUnit.net属性,这是一个很好的选择! –