сомневаемся в остальных. Как раз для этого случая в QuickCheckпредусмотрена функция a ==>b. Это функ-
ция обозначает условную проверку, свойство b будет протестировано только в том случае, если свойство a
окажется верным. Иначе тестовые данные будут отброшены.
notBlueAndBlack a b =cond a &&cond b ==>prop1 a b
wherecond ( Sta _) =a /= Blue &&a /= Black
Далее тестируем как обычно:
*Test>quickCheck notBlueAndBlack
+++ OK, passed 100 tests .
Также с помощью функции forAll мы можем подсказать QuickCheckна каких данных тестировать свой-
ство.
forAll ::( Showa, Testableprop) => Gena ->(a ->prop) -> Property
Эта функция принимает генератор случайных значений и свойство, которое зависит от тех значений,
которые создаются этим генератором. К примеру, пусть нас интересуют только все возможные пути между
четырьмя станциями: ( St Blue De), ( St Red Lao), ( St Green Til) и ( St Orange Sever). Воспользуемся
функцией elements ::[a] -> Gena, она как раз принимает список значений, и возвращает генератор,
который случайным образом выбирает любое значение из этого списка.
testFor =forAll (liftA2 (,) gen gen) $uncurry prop1
wheregen =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 $\( Only4a) ( Only4b) ->prop1 a b
+++ OK, passed 100 tests .
*Test>quickCheck $\( Only4a) ( OnlyOrangeb) ->prop1 a b
+++ OK, passed 100 tests .
*Test>quickCheck $\a ( OnlyOrangeb) ->prop2 a b
+++ OK, passed 100 tests .
Классификация тестовых случаев
Мы можем попросить у QuickCheck, чтобы он разбил тестовую выборку на классы и в конце тестирования
сообщил бы нам сколько элементов в какой класс попали. Это делается с помощью функции classify:
classify :: Testableprop => Bool -> String ->prop -> Property
Она принимает условие классификации, метку класса и свойство. Например так мы можем разбить вы-
борку по типам линий:
prop3 :: Station -> Station -> Property
prop3 a @( Stwa _) b @( Stwb _) =
classify (wa == Orange ||wb == Orange) ”Orange” $
classify (wa == Black
||wb == Black)
”Black”
$
classify (wa == Red
||wb == Red)
”Red”
$prop1 a b
Протестируем:
*Test>quickCheck prop3
+++ OK, passed 100 tests :
34 % Red
15 % Orange
9 % Black
8 % Orange, Red
6 % Black, Red
5 % Orange, Black
19.3 Оценка быстродействия с помощью criterion
Недавно появилась библиотека unordered -containers. Она предлагает более эффективную реализацию
нескольких структур из стандартной библиотеки containers. Например там мы можем найти тип HashSet.
Почему бы нам не заменить на него стандартный тип Set?
Оценка быстродействия с помощью criterion | 283
cabal install unordered -containers
Изменения отразятся лишь на контекстах объявлений типов. Элементы принадлжежащие множеству
HashSetдолжны быть экземплярами классов Eqи Hashable. Новый класс Hashableнужен для ускорения
работы с данными. Давайте посмотрим на этот класс:
Читать дальше