Вчера, с подачи
antilamer (спасибо за вдохновляющий поток эмоций! :)), поразбирался с
QuickCheck - средством для тестирования функционального кода, которое основывается на проверках неких свойств, которые задаются относительно определённых функций и проверяются на случайно сгенерированных данных.
Классический пример: есть функция reverse для обращения списков. Тогда можно придумать такие достаточно ярко её характеризующие свойства:
propReverseUnit x = reverse [x] == [x]
-- (то есть, обращая список из одного элемента - получаем тот же список)
propReverseAppend xs ys = reverse (xs++ys) == reverse ys ++ reverse xs
-- (обращая конкатенацию списков, получаем конкатенацию обращений частей
-- в обратном порядке)
propReverseReverse xs = reverse (reverse xs) == xs
-- (обращая обращение списка - получаем тот же список)
Теперь из-под
ghci запускаем
QuickCheck:
Main> quickCkeck propReverseReverse
OK, 100 tests passed
и - вот он, момент истины! - QuickCheck сгенерил 100 случайных списков, на которых проверил данное свойство и поскольку оно всегда выполнилось - выдал
OK.
При этом свойства могут быть и посложнее нежели описанные выше - в них могут присутствовать необходимые для выполнения свойства условия, генерируемые данные могут быть определённым образом классифицированы, кроме этого можно создавать свои генераторы значений, в том числе для рекурсивных типов (легко!) и даже генераторы случайных функций!
Для того, чтобы дополнительно управлять случайными значениями, которые генерятся и направлять эти значения в нужное русло - существуют понятие "генератор", которые можно (и иногда нужно) описывать для своих и стандартных типов данных, а также некоторый небольшой фрэймворк, который позволяет эти генераторы комбинировать с помощью стандартных, довольно удобных и отлично продуманных комбинаторов - получая при этом новые необходимые генераторы.
На предстоящей встрече Spb Haskell User Group , как раз ожидается доклад по QuickCheck от Дмитрия Тимофеева (
dtim), который, думаю, будет весьма интересно послушать, при этом уточнив пока неясные для меня моменты.
В общем, весьма любопытная штука и немного необычный (по крайней мере для меня) подход к тестированию, который отлично работает в условиях отсутствия побочных эффектов и превращает процесс тестирования в весьма увлекательный процесс размышления над свойствами своей программы. Изначально QuickCheck был написан для Haskell и активно там используется, но поиск в гугле выдал и порт для Erlang .
Настроение: |
geeky |