Asynchronous 如何在FsCheck中运行异步测试?

Asynchronous 如何在FsCheck中运行异步测试?,asynchronous,f#,fscheck,Asynchronous,F#,Fscheck,如何使用FsCheck获得可重复的异步测试?以下是我在FSI中运行的示例代码: let prop_simple() = gen { let! s = Arb.generate<string> printfn "simple: s = %A" s return 0 < 1 } let prop_async() = async { let s = Arb.generate<string> |> Gen.sample

如何使用FsCheck获得可重复的异步测试?以下是我在FSI中运行的示例代码:

let prop_simple() = gen {
    let! s = Arb.generate<string>
    printfn "simple: s = %A" s
    return 0 < 1
}
let prop_async() =
    async {
        let s = Arb.generate<string> |> Gen.sample 10 1 |> List.head
        // let! x = save_to_db s // for example
        printfn "async: s = %A" s
        return 0 < 1
    } 
    |> Async.RunSynchronously

let check_props() = 
    //FC2.FsCheckModifiers.Register()
    let config = 
        { FsCheck.Config.Default with 
            MaxTest = 5
            Replay = Random.StdGen(952012316,296546221) |> Some
        }
    Check.One(config, prop_simple)
    Check.One(config, prop_async)
另一次跑步可以如下所示:

simple: s = "VDm2JQs5z"
simple: s = "NVgDf2mQs8zaWELndK"
simple: s = "TWz3Yjl2tHFERyrMTvl0HOqgx"
simple: s = "KRWC92vBdZAHj6qcf"
simple: s = "CTJbQGXzpLBNn0RY6MCvlfUtbQhCUKm9tbXFhLSu0RcYmi"
Ok, passed 5 tests.
async: s = "aOE"
async: s = "y8"
async: s = "y8"
async: s = "q"
async: s = "q"
Ok, passed 5 tests.
simple: s = "VDm2JQs5z"
simple: s = "NVgDf2mQs8zaWELndK"
simple: s = "TWz3Yjl2tHFERyrMTvl0HOqgx"
simple: s = "KRWC92vBdZAHj6qcf"
simple: s = "CTJbQGXzpLBNn0RY6MCvlfUtbQhCUKm9tbXFhLSu0RcYmi"
Ok, passed 5 tests.
async: s = "g"
async: s = "g"
async: s = "g"
async: s = ""
async: s = ""
Ok, passed 5 tests.
因此
prop_simple()
工作正常且可重复(给定
StdGen(952012316296546221)

但是
prop\u async()
是不可重复的&似乎一次又一次地生成相同的字符串


另外,有没有更好的方法来编写
prop_async()

FsCheck的行为与这里的
async
没有任何关系,而是与
async
内部使用的
Gen.sample
有关
Gen.sample
为每次调用选择一个新的基于时间的种子-因此它在FsCheck属性中的行为是不可复制的。换句话说,您不应该在属性中使用它,当您编写一个新的生成器时,它只是用于探索目的。由于种子是基于时间的,并且您的属性非常小,因此多个调用将使用相同的种子,因此您可以看到相同的值。例如,这里有一个属性没有任何具有相同行为的
async

让prop_simple2()
设s=Arb.generate |>Gen.sample 10 1 |>List.head
//让我来!例如,x=将_保存到_db s//
printfn“simple2:s=%A”s
0 < 1
印刷品

simple2: s = "nrP?.PFh^y"
simple2: s = "nrP?.PFh^y"
simple2: s = "nrP?.PFh^y"
simple2: s = "nrP?.PFh^y"
simple2: s = "nrP?.PFh^y"
Ok, passed 5 tests.
现在,关于如何编写
async
属性,我将在属性中保留异步性,然后使用
async.RunSynchronously
将其解析为正常值。作为示例的变体:

让prop_async2=
根{
让!s=Arb.generate
//例如,让!x=将_保存到_db s//
设r=
异步的{
printfn“async2:s=%A”s
}
|>异步运行
返回0<1
}

它具有确定性输出。(另外请注意,如果您已经创建了
GenI,我怀疑您的异步启动的距离足够近,以至于您同时为其中的几个获得了相同的基于时间戳的随机种子,这导致了您看到的重复样本。我建议您尝试一下哪个系统可以异步运行FsCheck属性。我没有曾经使用过它,所以我不能给你更多的帮助,这就是为什么这是一个评论而不是一个答案。expecto看起来非常有用。谢谢!这也回答了我的许多其他问题。非常感谢。现在我可以做一些非常令人印象深刻的测试!!