Используя FsCheck, я получаю разные результаты на тестах, когда 100% пройдено, а в другое время ошибка - PullRequest
2 голосов
/ 29 мая 2019

Я создал генератор для генерации списков int одинаковой длины и для проверки свойств zip и unzip.При запуске теста я получаю время от времени ошибку

Ошибка: System.ArgumentException: list2 на 1 элемент короче list1

, но это не должно происходить из-замой генератор.

Я трижды прошел 100% тест, а затем ошибку выше.Зачем?Кажется, мой генератор не работает должным образом.

let samelength (x, y) = 
    List.length x = List.length y

let arbMyGen2 = Arb.filter samelength Arb.from<int list * int list> 

type MyGenZ =
    static member genZip() = 
       {
        new Arbitrary<int list * int list>() with
            override x.Generator = arbMyGen2 |> Arb.toGen
            override x.Shrinker t = Seq.empty
    }

let _ = Arb.register<MyGenZ>()

let pro_zip (xs: int list, ys: int list) = 
   (xs, ys) = List.unzip(List.zip xs ys)
   |> Prop.collect (List.length xs = List.length ys)

do Check.Quick pro_zip

1 Ответ

1 голос
/ 31 мая 2019

Ваш код, как написано, у меня работает. Так что я не уверен, что именно не так, но я могу дать вам несколько полезных (надеюсь!) Подсказок.

В первую очередь, попробуйте не использовать механизм регистрации, а вместо этого использовать Prop.forAll, как показано ниже:

let pro_zip  = 
   Prop.forAll arbMyGen2 (fun (xs,ys) ->
        (xs, ys) = List.unzip(List.zip xs ys)
        |> Prop.collect (List.length xs))

do Check.Quick pro_zip

Примечание. Я также изменил ваш вызов Prop.collect, чтобы собрать длину списка (ов), что дает несколько более интересные результаты. Фактически ваше свойство уже проверяет, что списки имеют одинаковую длину (хотя и неявно), поэтому тест не пройдёт с контрпримером, если они не совпадают.

Arb.filter преобразует существующий Arbitrary (то есть генератор и фильтр) в новый Arbitrary. Другими словами, arbMyGen2 имеет функцию сжатия, которая будет работать (т. Е. Возвращает только меньшие пары списков равной длины), тогда как в genZip() вы выбрасываете усадку. Было бы хорошо просто написать

type MyGenZ =
    static member genZip() = arbMyGen2

вместо.

...