C#中的FsCheck:生成具有相同形状的二维数组的列表 [英] FsCheck in C#: generate a list of two dimension arrays with the same shape

查看:27
本文介绍了C#中的FsCheck:生成具有相同形状的二维数组的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我正在编写一些用于视频分析的代码.这是 Video 类的简化版本:

Let's say I'm writing some code for video analysis. Here is a simplified version of a Video class:

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 做一个收缩器?

How do I make an Arbitrary<Video> and register it? How do I make a shrinker for that Arbitrary?

尝试过这个,无法理解 apply 是如何工作的:

Tried this, couldn't understand how apply works:

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();
}

尝试过这个,但无法在此处插入列表的生成器:

Tried this, but couldn't plug the generator for list in here:

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 类编写 Arbitrary:

Using Kurt Schelfthout's answer as a foundation, you can write an Arbitrary for the video class like this:

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();
    }
}

您可以通过多种方式使用它.

You can use this in various ways.

以下是将 Video Arbitrary 与普通 FsCheck 结合使用的方法,此处托管在 xUnit.net 测试用例中,这不是必需的:您可以在任何您喜欢的过程中托管它:

Here's how to use the Video Arbitrary with plain vanilla FsCheck, here hosted within an xUnit.net test case, which isn't required: you can host this in whichever process you prefer:

[Fact]
public void VideoProperty()
{
    var property = Prop.ForAll(
        VideoArbitrary.Videos(),
        video =>
        {
            // Test goes here...
            Assert.NotNull(video);
        });
    property.QuickCheckThrowOnFailure();
}

Prop.ForAll 对于使用自定义任意值定义属性非常有用.当您调用 QuickCheckThrowOnFailure 时,它将运行 Video 类的所有"(默认为 100)值的测试.

Prop.ForAll is very useful for defining properties with custom Arbitraries. When you call QuickCheckThrowOnFailure, it's going to run the test for 'all' (by defailt: 100) values of the Video class.

您也可以使用 FsCheck.Xunit Glue 库,但您必须将 Arbitrary 作为弱类型值传递给属性:

You can also use the FsCheck.Xunit Glue Library, but you have to pass the Arbitrary as a weakly typed value to the attribute:

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

这简单易懂,但在分配Arbitrary属性时不涉及静态类型检查,所以我不太喜欢这种方法.

This is simple and easy to understand, but there's no static type checking involved when assigning that Arbitrary property, so I'm not too fond of this approach.

将 FsCheck.Xunit 与自定义 Arbitraries 一起使用的更好方法是将它结合起来与 Prop.ForAll:

A better way to use FsCheck.Xunit with custom Arbitraries is to combine it with Prop.ForAll:

[Property]
public Property XUnitPropertyWithStronglyTypedArbitrary()
{
    return Prop.ForAll(
        VideoArbitrary.Videos(),
        video =>
        {
            // Test goes here...
            Assert.NotNull(video);
        });
}

注意这个方法的返回类型不再是void,而是Property[Property] 属性理解这种类型并相应地执行测试.

Notice that the return type of this method is no longer void, but Property; the [Property] attribute understands this type and executes the test accordingly.

这第三个选项是我在 xUnit.net 中使用自定义 Arbitraries 的首选方式,因为它带回了编译时检查.

This third option is my preferred way of using custom Arbitraries from within xUnit.net, because it brings back compile-time checking.

这篇关于C#中的FsCheck:生成具有相同形状的二维数组的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆