Читаем Учебник по Haskell полностью

Мы воспользовались двумя функциями из бибилотеки QuickCheck. Это vector и choose. Первая строит

список случайных чисел заданной длины, а вторая выбирает случайное число из заданного диапазона. Теперь

мы можем протетстировать наши предикаты с помощью функции quickCheck:

*Test Prelude> quickCheck prop1

+++ OK, passed 100 tests.

*Test Prelude> quickCheck prop2

+++ OK, passed 100 tests.

*Test Prelude>

Свойства прошли тестирование на выборке из 100 комбинаций аргументов. Если нам интересно, мы

можем с помощью функции verboseCheck посмотреть на каких именно значениях проводилось тестирование:

Тестирование с помощью QuickCheck | 281

*Test Prelude> verboseCheck prop2

Passed:

St Black Kosmodrom

St Red UlBylichova

Passed:

St Black UlBylichova

St Orange Sever

Passed:

St Red Sirius

St Blue Krest

...

Если бы свойство не выполнилось, QuickCheck сообщил бы нам об этом и показал бы те элементы, для

которых свойство не выполнилось. Давайте составим такое свойство искусственно. Например, проверим,

находятся ли все станции на одной линии:

fakeProp :: Station -> Station -> Bool

fakeProp (St a _) (St b _) = a == b

Посмотрим, что на это скажет QuickCheck:

*Test Prelude> quickCheck fakeProp

*** Failed! Falsifiable (after 1 test):

St Green Sirius

St Blue Rodnik

По умолчанию QuickCheck проверит свойство сто раз. Для изменения этих настроек, мы можем восполь-

зоваться функцией quickCheckWith, дополнительным параметром она принимает значение типа Arg, которое

содержит параметры тестирования. Например протестируем первое свойство 500 раз:

*Test> quickCheckWith (stdArgs{ maxSuccess = 500 }) prop1

+++ OK, passed 500 tests.

Мы воспользовались стандартными настройками (stdArgs) и изменили один параметр.

Формирование тестовой выборки

Предположим, что мы уверены в правильной работе алгоритма для голубой и чёрной ветки метро, но

сомневаемся в остальных. Как раз для этого случая в QuickCheck предусмотрена функция a==> b. Это функ-

ция обозначает условную проверку, свойство b будет протестировано только в том случае, если свойство a

окажется верным. Иначе тестовые данные будут отброшены.

notBlueAndBlack a b = cond a && cond b ==> prop1 a b

where cond (St a _) = a /= Blue && a /= Black

Далее тестируем как обычно:

*Test> quickCheck notBlueAndBlack

+++ OK, passed 100 tests.

Также с помощью функции forAll мы можем подсказать QuickCheck на каких данных тестировать свой-

ство.

forAll :: (Show a, Testable prop) => Gen a -> (a -> prop) -> Property

Эта функция принимает генератор случайных значений и свойство, которое зависит от тех значений,

которые создаются этим генератором. К примеру, пусть нас интересуют только все возможные пути между

четырьмя станциями: (St Blue De), (St Red Lao), (St Green Til) и (St Orange Sever). Воспользуемся

функцией elements :: [a] -> Gen a, она как раз принимает список значений, и возвращает генератор,

который случайным образом выбирает любое значение из этого списка.

testFor = forAll (liftA2 (,) gen gen) $ uncurry prop1

where gen = elements [St Blue De, St Red Lao,

St Green Til, St Orange Sever]

Проверим, те ли значения попали в выборку:

282 | Глава 19: Ориентируемся по карте

*Test> verboseCheckWith (stdArgs{ maxSuccess = 3 }) testFor

Passed:

(St Blue De, St Orange Sever)

Passed:

(St Orange Sever, St Red Lao)

Passed:

(St Red Lao, St Red Lao)

+++ OK, passed 3 tests.

Мы можем настроить формирование выборки ещё одним способом. Для этого мы сделаем специальный

тип обёртку над Station и определим для ненго свой экземпляр класса Arbitrary:

newtype OnlyOrange = OnlyOrange Station

newtype Only4

= Only4

Station

instance Arbitrary OnlyOrange where

arbitrary = OnlyOrange . St Orange <$>

elements [DnoBolota, PlBakha, Krest, Lao, Sever]

instance Arbitrary Only4 where

arbitrary = Only4 <$> elements [St Blue De, St Red Lao,

St Green Til, St Orange Sever]

После этого мы можем очень легко комбинировать различные выборки при тестировании.

*Test> quickCheck $ \(Only4 a) (Only4 b) -> prop1 a b

+++ OK, passed 100 tests.

*Test> quickCheck $ \(Only4 a) (OnlyOrange b) -> prop1 a b

+++ OK, passed 100 tests.

*Test> quickCheck $ \a (OnlyOrange b) -> prop2 a b

+++ OK, passed 100 tests.

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных