假设我正在写一些视频分析代码。以下是视频类的简化版本:

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>并进行注册?我该怎么为那个武断的人做一个缩小器?
尝试过,无法理解apply的工作原理:
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对于使用自定义套利定义属性非常有用。当您调用QuickCheckThrowOnFailure时,它将对Video类的'all'(defilt:100)值运行测试。
非类型化xunit.net属性
也可以使用fscheck.xunit glue库,但必须将任意值作为弱类型值传递给属性:
[Property(Arbitrary = new[] { typeof(VideoArbitrary) })]
public void XunitPropertyWithWeaklyTypedArbitrary(Video video)
{
    // Test goes here...
    Assert.NotNull(video);
}

这很简单,也很容易理解,但是在分配Arbitrary属性时不涉及静态类型检查,所以我不太喜欢这种方法。
类型化xunit.net属性
使用fscheck.xunit进行自定义套利的更好方法是:
[Property]
public Property XUnitPropertyWithStronglyTypedArbitrary()
{
    return Prop.ForAll(
        VideoArbitrary.Videos(),
        video =>
        {
            // Test goes here...
            Assert.NotNull(video);
        });
}

注意,此方法的返回类型不再是void,而是Property;属性理解此类型并相应地执行测试。
第三个选项是我在xunit.net中使用自定义套利的首选方法,因为它带来了编译时检查。

关于c# - C#中的FsCheck:生成具有相同形状的二维数组的列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32811322/

10-10 05:19