[英]FsCheck in C#: generate a list of two dimension arrays with the same shape
假設我正在為視頻分析編寫一些代碼。 以下是Video類的簡化版本:
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();
}
使用Kurt Schelfthout的答案作為基礎,您可以像這樣為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一起使用,這里托管在xUnit.net測試用例中,這不是必需的:您可以在您喜歡的任何過程中托管它:
[Fact]
public void VideoProperty()
{
var property = Prop.ForAll(
VideoArbitrary.Videos(),
video =>
{
// Test goes here...
Assert.NotNull(video);
});
property.QuickCheckThrowOnFailure();
}
Prop.ForAll
對於使用自定義Arbitraries定義屬性非常有用。 當您調用QuickCheckThrowOnFailure
,它將運行Video
類的“all”(通過defailt:100)值的測試。
您也可以使用FsCheck.Xunit Glue Library,但您必須將Arbitrary作為弱類型值傳遞給屬性:
[Property(Arbitrary = new[] { typeof(VideoArbitrary) })]
public void XunitPropertyWithWeaklyTypedArbitrary(Video video)
{
// Test goes here...
Assert.NotNull(video);
}
這很簡單易懂,但是在分配Arbitrary
屬性時沒有涉及靜態類型檢查,所以我不太喜歡這種方法。
將FsCheck.Xunit與自定義Arbitraries一起使用的更好方法是將它與Prop.ForAll結合使用 :
[Property]
public Property XUnitPropertyWithStronglyTypedArbitrary()
{
return Prop.ForAll(
VideoArbitrary.Videos(),
video =>
{
// Test goes here...
Assert.NotNull(video);
});
}
請注意,此方法的返回類型不再是void
,而是Property
; [Property]
屬性理解此類型並相應地執行測試。
第三個選項是我在xUnit.net中使用自定義Arbitraries的首選方法,因為它帶回了編譯時檢查。
只是一刻的草圖 - 沒有編譯:)
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.