簡體   English   中英

C#中的FsCheck:生成具有相同形狀的二維數組的列表

[英]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

以下是如何將視頻任意與簡單的香草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)值的測試。

無法輸入xUnit.net屬性

您也可以使用FsCheck.Xunit Glue Library,但您必須將Arbitrary作為弱類型值傳遞給屬性:

[Property(Arbitrary = new[] { typeof(VideoArbitrary) })]
public void XunitPropertyWithWeaklyTypedArbitrary(Video video)
{
    // Test goes here...
    Assert.NotNull(video);
}

這很簡單易懂,但是在分配Arbitrary屬性時沒有涉及靜態類型檢查,所以我不太喜歡這種方法。

鍵入xUnit.net屬性

將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM