Предотвратяване на FsCheck от генериране на NaN и безкрайности

Имам дълбоко вложена структура от данни с плаващи навсякъде. Използвам FsCheck, за да проверя дали данните са непроменени след сериализиране и след това десериализиране.

Това свойство е неуспешно, когато float е или NaN, или +/- безкрайност, но такъв случай не ме интересува, тъй като не очаквам тези стойности да се появят в действителните данни.

Има ли начин да попреча на FsCheck да генерира NaN и безкрайности?

Опитах се да отхвърля генерирани данни, които съдържат споменатите стойности, но това прави теста невероятно бавен, всъщност толкова бавен, че тестът продължава да работи, докато пиша това, и имам съмнения, че наистина ще завърши...


person phaz    schedule 30.07.2014    source източник
comment
Използвайте обвивката NormalFloat github.com/fsharp/FsCheck/ blob/master/src/FsCheck/ github.com/fsharp/FsCheck/blob/master/src/FsCheck/   -  person Mauricio Scheffer    schedule 30.07.2014
comment
О готино. И така, как да направя това? :-)   -  person phaz    schedule 30.07.2014
comment
Направете вашите тестови параметри от тип NormalFloat.   -  person Mauricio Scheffer    schedule 30.07.2014
comment
Съжалявам, но пак не разбирам какво се опитваш да кажеш. Данните, които трябва да бъдат генерирани, са запис на записи на записи (sorta), някои от които съдържат плаващи елементи сред други неща. Бих искал всички места, където трябва да се генерират плаващи числа, да не използват NaN или безкрайности.   -  person phaz    schedule 30.07.2014
comment
Написахте ли свой собствен генератор за тези данни или използвате вградения генератор, базиран на отражение?   -  person Kurt Schelfthout    schedule 30.07.2014
comment
Имам същите проблеми като @Phazyck. В моя код from‹int› не работи. Всички функции на FsCheck са толкова сложни и недокументирани, така че входната бариера за използване на тази рамка е много висока. напр. Написах генератор за създаване на четни числа. След това направих Arbitrary‹int› с него, но не работи. Моля, направете го по-просто и по-добре документирано. Сега не се нуждаем от повече функции, имаме нужда от повече примери и документи.   -  person Endrju    schedule 23.08.2014


Отговори (2)


За рефлективно генерирани типове, които съдържат плаващи числа (както подозирам, че използвате), можете да презапишете генератора по подразбиране за плаващи числа, като напишете клас, както следва:

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.

Можете да проверите резултата от метода register, за да видите как той обедини произволните екземпляри по подразбиране с новите; трябваше да ги отмени.

Ако използвате разширението xUnit, можете да избегнете извикването на Arb.register, като използвате аргумента Arbitraries на PropertyAttribute:

[<Property(Arbitraries=Overides)>]
person Kurt Schelfthout    schedule 30.07.2014
comment
Имате ли нещо против да разширите последния си абзац с пример за това как ще бъде направено това? - person primfaktor; 30.06.2016

Както каза 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.
person jindraivanek    schedule 30.07.2014
comment
Предполагам, че това може да работи в други случаи, като тези, които илюстрирате. Проблемът е, че данните не са просто списък с float или нещо подобно, което ми позволява да напиша NormalFloat като част от типа, а по-сложна структура, която съдържа float на всякакви места, но също и други типове. Това, от което се нуждая, е да имам FsCheck, за да генерирам NormalFloats на всяко място, където е необходим float, без значение как изглеждат данните, както показва Kurt Schelfthout. :-) - person phaz; 31.07.2014