Если у вас есть ограничения, ограничивающие значения небольшим подмножеством всех разрешенных значений для данного типа, создание допустимого значения проще и безопаснее 1 , чем фильтрация.
Учитывая...
open FsCheck
open System
type QueryRequest = {Symbol: string; StartDate: DateTime; EndDate: DateTime}
... мы можем начать с создания генератора символов:
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
Убедитесь, что существует высокая вероятность того, что предикат удовлетворен.