Haskell quickcheck-как генерировать только строки для печати
У меня есть набор простых демонстрационных программ, которые кодируют / декодируют строки и хотят создать некоторые quickCheck тесты для них, но ограничить тесты только для печати строк. Использование guard слишком медленно и терпит неудачу из-за слишком большого количества сгенерированных и отклоненных тестовых случаев, поэтому я хочу создать безопасный генератор для этого домена.
ссылки на это, которые я видел, говорят либо (1) Определить свой собственный произвольные экземпляр Char и используйте это для создания только печатаемых символов для строк или (2) для обертывания самих функций в newtype и писать произвольные экземпляр для этого.
но попытка сделать (1) не удается, потому что теперь есть определение для этого в тесте.QuickCheck, и как бы это сделать-создать safeChar генератор для нового типа, а затем снова должен произвести адаптер для проверенных функций? (Раздел книги RWH об этом отмечает, что он устарел в рекомендации этого определения DIY Char.)
попытка сделать (2) кажется, что я могу либо просто добавить защиту к тестовому предложению, которое локализовано и просто (но терпит неудачу), либо написать новую оболочку и связанный генератор, который кажется более беспорядочным.
очевидно, что это просто(!) и все инструменты предоставлены, но может ли кто-нибудь посоветовать, если это правильный анализ, и дать пример того, как лучше всего это сделать?
2 ответов
отправной точкой, безусловно, является genSafeChar
генератор, который может иметь тип Gen Char
. Например:
genSafeChar :: Gen Char
genSafeChar = elements ['a'..'z']
тогда вы можете построить это в genSafeString
генератор, например, с listOf
:
genSafeString :: Gen String
genSafeString = listOf genSafeChar
на данный момент у вас есть несколько разумных решений. Либо сделайте newtype
обертка для String
:
newtype SafeString = SafeString { unwrapSafeString :: String }
deriving Show
instance Arbitrary SafeString where
arbitrary = SafeString <$> genSafeString
(в этом случае вы можете просто подставить определение genSafeString
)
и вы можете использовать его что-то вроде этого:--14-->
testWibble (SafeString str) = str == str
или, вы можете использовать forAll
в каждой точке вам нужна безопасная строка:
testWibble = forAll genSafeString $ \str -> str == str
в настоящее время QuickCheck
есть PrintableString
тип, который также имеет экземпляр arbitrary
, что означает, что вы можете легко создавать произвольные строки:
arbitraryPrintableString :: Gen String
arbitraryPrintableString = getPrintableString <$> arbitrary