13

ビデオ分析用のコードを書いているとしましょう。以下は、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();
}
4

2 に答える 2

15

Kurt Schelftout の答えを基礎として使用すると、次のvideoようにクラスの Arbitrary を作成できます。

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 テスト ケース内でホストされているプレーンなバニラ FsCheck で Video Arbitrary を使用する方法を示します。

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

Prop.ForAllカスタム Arbitraries でプロパティを定義するのに非常に便利です。を呼び出すとQuickCheckThrowOnFailure、クラスの「すべて」(デフォルト: 100) の値のテストが実行されますVideo

型指定されていない xUnit.net プロパティ

FsCheck.Xunit Glue ライブラリを使用することもできますが、Arbitrary を弱く型付けされた値として属性に渡す必要があります。

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

これはシンプルで理解しやすいですが、そのArbitraryプロパティを割り当てるときに静的な型チェックが含まれていないため、私はこのアプローチがあまり好きではありません。

型付き xUnit.net プロパティ

カスタム Arbitraries で FsCheck.Xunit を使用するより良い方法は、それを Prop.ForAll と組み合わせることです

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

このメソッドの戻り値の型はvoidではなくProperty;であることに注意してください。[Property]属性はこのタイプを理解し、それに応じてテストを実行します。

この 3 番目のオプションは、xUnit.net 内からカスタム Arbitraries を使用する場合に私が好む方法です。これにより、コンパイル時のチェックが復活するからです。

于 2015-09-29T11:48:54.900 に答える