Предотвращение FsCheck от генерации NAN и бесконечностей
-
21-12-2019 - |
Вопрос
У меня глубоко вложенная фазаструктура с поплавками по всему месту. Я использую fscheck, чтобы проверить, не изменяется ли данные после сериализации, а затем десериализация.
Это свойство не удается, когда поплавок либо NAN, либо +/- бесконечность, однако, такой случай не интересует меня, поскольку я не ожидаю, что эти значения произошли в фактических данных.
Есть ли способ предотвратить Fscheck от генерации NAN и бесконечностей?
Я пытался отбрасывать сгенерированные данные, которые содержат указанные значения, но это делает тест невероятно медленным, поэтому медленно на самом деле, что тест все еще работает, пока я пишу это, и у меня есть мои сомнения, на самом деле заканчивается...
Решение
Для отражающих сгенерированных типов, которые содержат поплавки (как я подозреваю, что вы используете), вы можете перезаписать генератор по умолчанию для поплавков, написав класс следующим образом:
type Overrides() =
static member Float() =
Arb.Default.Float()
|> filter (fun f -> not <| System.Double.IsNaN(f) &&
not <| System.Double.IsInfinity(f))
.
а затем вызов:
Arb.register<Overrides>()
.
до того, как fscheck пытается генерировать типы;напримерв вашей настройке теста или перед вызовом check.quick.
Вы можете проверить результат метода регистра, чтобы увидеть, как он объединил произвольные экземпляры по умолчанию с новыми;Это должно было переопределить их.
Если вы используете расширение XUNIT, вы можете избежать вызова ARB.Register, используя арбитра арбитра PropertyAttribute:
[<Property(Arbitraries=Overides)>]
. Другие советы
Как сказал Mauricio Scheffer, вы можете использовать тип NormalFloat в тестовом параметре.
Простой пример для списка поплавков:
open FsCheck
let f (x : float list) = x |> List.map id
let propFloat (x : float list) = x = (f x)
let propNormalFloat (xn : NormalFloat list) =
let x = xn |> List.map NormalFloat.get
x = f x
Check.Quick propFloat
//Falsifiable, after 18 tests (13 shrinks) (StdGen (761688149,295892075)):
//[nan]
Check.Quick propNormalFloat
//Ok, passed 100 tests.
.