使用 FsCheck 生成记录
Using FsCheck to Generate Records
我想使用 FsCheck(与 XUnit)创建类型的记录:type QueryRequest = {Symbol: string; StartDate: DateTime; EndDate: DateTime}
其中 Symbol
仅限于 3 个选项 - ORCL
、IBM
、AAPL
、StartDate
和EndDate
仅限于2000年1月1日和2019年1月1日.
但是,我不清楚如何进行。我应该使用 Arb.generate<T>
或 Arb.Default
或其他一些实用程序来生成和缩小测试用例吗?
更新 1
与生成记录的问题相关的后续问题可用 here。
Original:
{ Symbol = ""
StartDate = 8/9/2057 4:07:10 AM
EndDate = 10/14/2013 6:15:32 PM }
Shrunk:
{ Symbol = ""
StartDate = 8/9/2057 12:00:00 AM
EndDate = 10/14/2013 12:00:00 AM }
更新 2
以下是测试套件代码:
namespace Parser
open Xunit
open FsCheck.Xunit
open DataGenerators
module Tests =
[<Fact>]
let ``sanity check`` () =
let expected = true
let actual = true
Assert.Equal(expected, actual)
[<Property(Arbitrary = [|typeof<StockTwitGenerator>|])>]
let ``validate queries`` (q: QueryRecord) =
q.EndDate > q.StartDate
Arb.filter 过滤给定 Arbitrary 实例的生成器和收缩器,以仅包含与给定过滤函数匹配的那些值。这应该可以帮助您满足您的需求。
https://fscheck.github.io/FsCheck/TestData.html#Useful-methods-on-the-Arb-module
https://github.com/fscheck/FsCheck/blob/master/src/FsCheck/ArbitraryExtensions.fs#L17-17
当您具有将值限制为给定类型的所有允许值的一小部分的约束时,构造有效值比过滤更容易和更安全1。
鉴于...
open FsCheck
open System
type QueryRequest = {Symbol: string; StartDate: DateTime; EndDate: DateTime}
...我们可以从为 Symbols 创建一个生成器开始:
let symbols = ["ORCL"; "IBM"; "AAPL"]
let symbol = Gen.elements symbols
和日期范围
let minDate = DateTime(2000, 1, 1)
let maxDate = DateTime(2019, 1, 1)
let dateRange = maxDate - minDate
let date =
Gen.choose (0, int dateRange.TotalDays)
|> Gen.map (float >> minDate.AddDays)
请注意 Gen.choose
只接受 int
范围。我们可以通过生成最大允许日期差异的随机偏移量然后映射回 DateTime
来解决
使用这些,我们可以为 QueryRequest
s...
构造一个生成器
let query =
gen {
let! s = symbol
let! d1 = date
let! d2 = date
let startDate, endDate = if d1 < d2 then d1, d2 else d2, d1
return { Symbol = s; StartDate = startDate; EndDate = endDate }
}
type MyGenerators =
static member QueryRequest() =
{new Arbitrary<QueryRequest>() with
override _.Generator = query }
...注册...
Arb.register<MyGenerators>()
最后测试:
let test { Symbol = s; StartDate = startDate; EndDate = endDate } =
symbols |> Seq.contains s && startDate >= minDate && endDate <= maxDate && startDate <= endDate
Check.Quick test
1
FsCheck 文档
Make sure there is a high chance that the predicate is satisfied.
我想使用 FsCheck(与 XUnit)创建类型的记录:type QueryRequest = {Symbol: string; StartDate: DateTime; EndDate: DateTime}
其中 Symbol
仅限于 3 个选项 - ORCL
、IBM
、AAPL
、StartDate
和EndDate
仅限于2000年1月1日和2019年1月1日.
但是,我不清楚如何进行。我应该使用 Arb.generate<T>
或 Arb.Default
或其他一些实用程序来生成和缩小测试用例吗?
更新 1
与生成记录的问题相关的后续问题可用 here。
Original: { Symbol = "" StartDate = 8/9/2057 4:07:10 AM EndDate = 10/14/2013 6:15:32 PM } Shrunk: { Symbol = "" StartDate = 8/9/2057 12:00:00 AM EndDate = 10/14/2013 12:00:00 AM }
更新 2
以下是测试套件代码:
namespace Parser
open Xunit
open FsCheck.Xunit
open DataGenerators
module Tests =
[<Fact>]
let ``sanity check`` () =
let expected = true
let actual = true
Assert.Equal(expected, actual)
[<Property(Arbitrary = [|typeof<StockTwitGenerator>|])>]
let ``validate queries`` (q: QueryRecord) =
q.EndDate > q.StartDate
Arb.filter 过滤给定 Arbitrary 实例的生成器和收缩器,以仅包含与给定过滤函数匹配的那些值。这应该可以帮助您满足您的需求。
https://fscheck.github.io/FsCheck/TestData.html#Useful-methods-on-the-Arb-module https://github.com/fscheck/FsCheck/blob/master/src/FsCheck/ArbitraryExtensions.fs#L17-17
当您具有将值限制为给定类型的所有允许值的一小部分的约束时,构造有效值比过滤更容易和更安全1。
鉴于...
open FsCheck
open System
type QueryRequest = {Symbol: string; StartDate: DateTime; EndDate: DateTime}
...我们可以从为 Symbols 创建一个生成器开始:
let symbols = ["ORCL"; "IBM"; "AAPL"]
let symbol = Gen.elements symbols
和日期范围
let minDate = DateTime(2000, 1, 1)
let maxDate = DateTime(2019, 1, 1)
let dateRange = maxDate - minDate
let date =
Gen.choose (0, int dateRange.TotalDays)
|> Gen.map (float >> minDate.AddDays)
请注意 Gen.choose
只接受 int
范围。我们可以通过生成最大允许日期差异的随机偏移量然后映射回 DateTime
使用这些,我们可以为 QueryRequest
s...
let query =
gen {
let! s = symbol
let! d1 = date
let! d2 = date
let startDate, endDate = if d1 < d2 then d1, d2 else d2, d1
return { Symbol = s; StartDate = startDate; EndDate = endDate }
}
type MyGenerators =
static member QueryRequest() =
{new Arbitrary<QueryRequest>() with
override _.Generator = query }
...注册...
Arb.register<MyGenerators>()
最后测试:
let test { Symbol = s; StartDate = startDate; EndDate = endDate } =
symbols |> Seq.contains s && startDate >= minDate && endDate <= maxDate && startDate <= endDate
Check.Quick test
1 FsCheck 文档
Make sure there is a high chance that the predicate is satisfied.