Можно ли генерировать произвольные функции в QuickCheck - PullRequest
0 голосов
/ 31 мая 2018

Я пытался написать тест QuickCheck для идентификации

f $ y = f y

Мой первоначальный план состоял в том, чтобы написать произвольный генератор, который возвращает функции & Integer, с подписью Gen (Int -> Int, Int)

и в тесте prop_DollerDoesNothing это приложение функции с / без $ дает тот же результат.

Это был мой код:

  prop_DollarDoesNothing :: Property
  prop_DollarDoesNothing =
    forAll arbitraryFuncInt (\(f, y) -> (f $ y) == (f y))

  arbitraryFuncInt :: Gen (Int -> Int, Int)
  arbitraryFuncInt = do
    f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
    y <- arbitrary :: Gen Int
    return (f, y)

И было сгенерировано следующее полезное сообщение об ошибке.:

    * No instance for (Show (Int -> Int))
        arising from a use of `forAll'
        (maybe you haven't applied a function to enough arguments?)
    * In the expression:
        forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))
      In an equation for `prop_DollarDoesNothing':
          prop_DollarDoesNothing
            = forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))

Итак, я исправил ошибку и получил тест на работу, применив произвольную функцию и вернув пару целых чисел из arbitraryFuncInt

  prop_DollarDoesNothing :: Property
  prop_DollarDoesNothing =
    forAll arbitraryFuncInt (\(x, y) -> x == y)

  arbitraryFuncInt :: Gen (Int, Int)
  arbitraryFuncInt = do
    f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
    y <- arbitrary :: Gen Int
    return (f $ y, f y)

Мои вопросы:

  1. просто невозможно вернуть произвольные функции, которые не были полностью применены из-за отсутствия экземпляра для Show?
  2. Могу ли я написать экземпляр для Show (Int -> Int) всделать возможным # 1?
  3. Может ли QuickCheck генерировать произвольные функции с учетом сигнатуры типа, для случаев, когда я проверяю идентичности, которые являются истинными для всех функций (данного типа).Выше я указываю 3 тестовые функции вручную, я хотел бы как-то автоматизировать это, в идеале что-то вроде этого f <- arbitrary :: Gen (Int -> Int)

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

QuickCheck поддерживает генерацию, сжатие и отображение функций, используя тип Fun.CoArbitrary позволяет генерировать функции.Затем он преобразуется в (возможно, бесконечную) триподобную структуру, которая может быть проверена и сокращена до конечного значения (поскольку сбой теста зависит только от конечного числа входных данных), которое затем может быть показано в качестве контрпримера.

Конкретно, вы можете написать свойства как функцию, которая принимает аргумент Fun, который является оберткой вокруг (->), используя механизм, который я описал.Разобрать его по шаблону Fn, чтобы получить функцию.

prop_dollarDoesNothing :: Property
prop_dollarDoesNothing = property $ \(Fn (f :: Int -> Int)) x ->
  (f $ x) === f x

Для получения дополнительной информации

0 голосов
/ 31 мая 2018

Arbitrary может сгенерировать функции очень хорошо (при условии, что аргументы являются экземплярами CoArbitrary), это просто часть показа, которая не работает.На самом деле нет хорошего способа показать функцию.

Это распространенная проблема, и поэтому QuickCheck предоставляет модификатор Blind.Он в основном подделывает Show экземпляров для любого типа, фактически не показывая никакой информации о значении.Конечно, это несколько снижает полезность отладки неудачного тестового примера, но с этим мало что можно сделать.

...