2015-09-27 18 views
12

Giả sử tôi đang viết một số mã để phân tích video. Đây là phiên bản đơn giản của lớp Video:FsCheck trong C#: tạo danh sách hai mảng thứ nguyên có cùng hình dạng

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

Làm cách nào để tạo Arbitrary<Video> và đăng ký? Làm thế nào để tôi làm cho một shrinker cho rằng tùy ý?

Cố gắng này, không thể hiểu cách áp dụng các công trình:

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

Cố gắng này, nhưng không thể cắm máy phát điện cho danh sách ở đây:

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

Trả lời

12

Sử dụng câu trả lời của Kurt Schelfthout làm nền tảng, bạn có thể viết một tùy ý r lớp học video như sau:

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

Bạn có thể sử dụng theo nhiều cách khác nhau.

Plain vanilla FsCheck

Dưới đây là làm thế nào để sử dụng Video Arbitrary với FsCheck vani đồng bằng, ở đây lưu trữ trong một trường hợp thử nghiệm xUnit.net, mà không yêu cầu: bạn có thể lưu trữ này trong bất cứ quá trình bạn thích:

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

Prop.ForAll là rất hữu ích để xác định thuộc tính với tùy ý. Khi bạn gọi QuickCheckThrowOnFailure, nó sẽ chạy thử nghiệm cho các giá trị 'tất cả' (theo defailt: 100) của lớp Video.

tài sản xUnit.net untyped

Bạn cũng có thể sử dụng FsCheck.Xunit Thư viện Keo, nhưng bạn phải vượt qua Arbitrary như một giá trị yếu gõ vào thuộc tính:

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

Đây là đơn giản và dễ hiểu, nhưng không có kiểm tra kiểu tĩnh nào liên quan khi gán thuộc tính Arbitrary, vì vậy tôi không thích cách tiếp cận này.

Typed xUnit.net tài sản

Cách tốt hơn để sử dụng FsCheck.Xunit với tùy chỉnh Arbitraries là combine it with Prop.ForAll:

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

Chú ý rằng kiểu trả về của phương pháp này là không còn void, nhưng Property ; thuộc tính [Property] hiểu loại này và thực hiện kiểm tra tương ứng.

Tùy chọn thứ ba này là cách ưa thích của tôi bằng cách sử dụng các Trọng số tùy chỉnh từ bên trong xUnit.net, bởi vì nó mang lại kiểm tra thời gian biên dịch.

+2

Tôi không biết thuộc tính xUnit.net đã nhập, đó là một lựa chọn tuyệt vời! –

6

Chỉ cần một thôi thúc của thời điểm hiện tại sketch - not compiled :)

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); 
+0

Điều đó đã cho tôi một khởi đầu tốt, nhưng tôi đã phải lung lay nó một chút trước khi nó biên dịch :) –

Các vấn đề liên quan