我已经设法让xUnit处理我的小样本组件.现在我想知道我是否也可以参加FsCheck.我的问题是,在为我的函数定义测试属性时,我很难过.
也许我只是没有一套好的样本函数,但是这些函数的测试属性是什么呢?
//transforms [1;2;3;4] into [(1,2);(3,4)]
pairs : 'a list -> ('a * 'a) list //'
//splits list into list of lists when predicate returns
// true for adjacent elements
splitOn : ('a -> 'a -> bool) -> 'a list -> 'a list list
//returns true if snd is bigger
sndBigger : ('a * 'a) -> bool (requires comparison)
Run Code Online (Sandbox Code Playgroud) 假设我正在为视频分析编写一些代码.以下是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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我如何制作Arbitrary<Video>和注册?如何为该任意制作收缩器?
试过这个,无法理解申请是如何运作的:
public static Arbitrary<Video> Videos()
{
var videoGen = Arb.Generate<PositiveInt>()
.SelectMany(w => Arb.Generate<PositiveInt>(), (w, h) => new …Run Code Online (Sandbox Code Playgroud) 问题
在F#中,我使用FsCheck生成一个对象(我在Xunit测试中使用它,但我可以完全在Xunit之外重新创建,所以我认为我们可以忘记Xunit).在FSI中运行20代,
25%的时间,一代人投掷:
System.ArgumentException: The input must be non-negative.
Parameter name: index
> at Microsoft.FSharp.Collections.SeqModule.Item[T](Int32 index, IEnumerable`1 source)
at FsCheck.GenBuilder.bind@62.Invoke(Int32 n, StdGen r0) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 63
at FsCheck.Gen.go@290-1[b](FSharpList`1 gs, FSharpList`1 acc, Int32 size, StdGen r0) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 295
at FsCheck.Gen.SequenceToList@297.Invoke(Int32 n, StdGen r) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 297
at FsCheck.GenBuilder.bind@62.Invoke(Int32 n, StdGen r0) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 63
at FsCheck.Gen.sample@155[a](Int32 size, Gen`1 gn, Int32 i, StdGen seed, FSharpList`1 samples) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 157
at FsCheck.Gen.Sample[a](Int32 size, Int32 n, Gen`1 gn) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Gen.fs:line 155
at …Run Code Online (Sandbox Code Playgroud)我想创建一个FsCheck生成器来生成"复杂"对象的实例.复杂,我指的是C#中的现有类,它具有许多子属性和集合.这些属性和集合又需要为它们生成数据.
想象一下,这个课程以Menu儿童系列命名,Dishes并且Drinks(我正在制作它,所以忽略了糟糕的设计).我想做以下事情:
Dishes和可变数量的Drinks.Dish和Drink实例以填充其属性.Menu使用FsCheck API 在实例上设置一些其他基本属性.如何为这种类型的实例编写生成器?这是一个坏主意吗?(我是基于财产的测试的新手).我已经阅读了文档,但到目前为止显然未能将其全部内化.
有一个很好的例子来生成记录,但这实际上只生成3个相同类型的值float.
考虑一个被歧视的联盟:
type DU = | Foo of string | Bar of int | Baz of decimal * float | Qux of bool
Run Code Online (Sandbox Code Playgroud)
我想DU用FsCheck 创建一个值列表,但我不希望这些值都是Qux这样的.
这个谓词已经存在:
let isQux = function Qux _ -> true | _ -> false
Run Code Online (Sandbox Code Playgroud)
第一次尝试
我第一次尝试创建一个DU没有Qux大小写的值列表是这样的:
type DoesNotWork =
static member DU () = Arb.from<DU> |> Arb.filter (not << isQux)
[<Property(MaxTest = 10 , Arbitrary = [| typeof<DoesNotWork> |])>]
let repro (dus : DU list) =
printfn "%-5b : …Run Code Online (Sandbox Code Playgroud) 使用F #Check(Haskell QuickCheck测试库的F#版本)从C#生成测试,我发现随机字符串生成器不生成空字符串.
using FsCheck.Fluent;
Spec.ForAny<string>(s => s != null).QuickCheck(); // always pass
Run Code Online (Sandbox Code Playgroud)
此外,似乎没有按设计处理空字符串,但我没有设法将其从文档中删除.例如,只需在两个字符串之间进行选择,其中一个为null,就不起作用:
var strings = Any.ValueIn<string>(null, "non-null string");
Spec.For(strings, s => true).QuickCheck(); // throws null ref exception
Run Code Online (Sandbox Code Playgroud)
字符串似乎是一种特殊情况,因为它处理自定义对象,如
class Thing {}
Run Code Online (Sandbox Code Playgroud)
当与空值混合时:
var objects = Any.ValueIn(null, new Thing());
Spec.For(objects, s => true).QuickCheck(); // pass
Run Code Online (Sandbox Code Playgroud) 我试图用FsCheck实现以下行为:我想创建一个生成MyUnion类型实例的生成器,每个字符串字段都是非null /空.
type MyNestedUnion =
| X of string
| Y of int * string
type MyUnion =
| A of int * int * string * string
| B of MyNestedUnion
Run Code Online (Sandbox Code Playgroud)
我的'真实'类型比它更大/更深MyUnion,并且FsCheck能够毫无问题地生成实例,但是联合情况的字符串字段有时是空的.(例如,它可能会生成B (Y (123, "")))
也许有一些明显的方法可以将FsCheck NonEmptyString和它的支持结合起来生成我遗漏的任意联合类型?
任何正确方向的提示/指针都非常感谢.
谢谢!
我是单元测试的n00b.我已经安装FsCheck.Nunit,并NUnitTestAdapter从的NuGet,我试图做基于属性的测试,主要是由灵感不可估量的斯科特Wlaschin.
我正在使用该[<Property>]属性,我希望能够"跳过"不符合测试要求的输入:
[<Property(MaxTest=10)>]
let ``Calling unzipTo with an invalid destination will yield a failure.`` badDest =
if Directory.Exists(badDest)
then // somehow skip to the next randomized input
else // do the actual test
Run Code Online (Sandbox Code Playgroud)
最简单的方法是什么?
我更喜欢FsCheck/NUnit的答案,如果它存在,但我也会考虑任何其他框架,其测试可以在Visual Studio中运行.(我以为我看到了一个框架,其中有一个简单的函数来完成这个,但我无法弄清楚它是什么.)
到目前为止,我更喜欢FsCheck.NUnit,因为它可以为F#类型(有区别的联合等)生成随机输入而无需额外的工作.
我想使用最新版本的NUnit,FsCheck和F#.但是,当我指向我的软件包的最新版本时,我的单元测试不会被发现.
但是,我发现了基于属性的测试(即FsCheck).
我的包裹如下:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FsCheck" version="2.4.0" targetFramework="net461" />
<package id="FsCheck.Xunit" version="2.4.0" targetFramework="net461" />
<package id="FSharp.Core" version="4.0.0.1" targetFramework="net461" />
<package id="FsUnit" version="2.2.0" targetFramework="net461" />
<package id="NUnit" version="3.2.1" targetFramework="net461" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net461" />
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net461" />
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net461" />
<package id="xunit.runner.visualstudio" version="2.1.0" targetFramework="net461" />
</packages>
Run Code Online (Sandbox Code Playgroud)
我的app.config如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9999.9999.9999.9999" newVersion="3.2.1" />
</dependentAssembly>
</assemblyBinding>
</runtime> …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现一个自定义Arbitrary生成 glob 语法模式,如a*c?. 我认为我的实现是正确的,只是在使用 Xunit 运行测试时,FsCheck 似乎没有使用自定义任意Pattern生成测试数据。当我使用 LINQPad 时,一切都按预期工作。这是代码:
open Xunit
open FsCheck
type Pattern = Pattern of string with
static member op_Explicit(Pattern s) = s
type MyArbitraries =
static member Pattern() =
(['a'..'c']@['?'; '*'])
|> Gen.elements
|> Gen.nonEmptyListOf
|> Gen.map (List.map string >> List.fold (+) "")
|> Arb.fromGen
|> Arb.convert Pattern string
Arb.register<MyArbitraries>() |> ignore
[<Fact>]
let test () =
let prop (Pattern p) = p.Length = 0
Check.QuickThrowOnFailure prop
Run Code Online (Sandbox Code Playgroud)
这是输出:
可证伪,经过 2 …