Safe Haskell | None |
---|---|
Language | Haskell2010 |
GenValidity
exists to make tests involving Validity
types easier and speed
up the generation of data for them.
Let's use the example from Data.Validity
again: A datatype that represents
primes.
To implement tests for this datatype, we would have to be able to generate
both primes and non-primes. We could do this with
(Prime $ arbitrary)
but this is tedious and inefficient.suchThat
isValid
The GenValid
type class allows you to specify how to (efficiently)
generate valid data of the given type to allow for easier and quicker testing.
Just instantiating GenUnchecked
already gives you access to a default instance
of GenValid
and GenInvalid
but writing custom implementations of these functions
may speed up the generation of data.
For example, to generate primes, we don't have to consider even numbers other than 2. A more efficient implementation could then look as follows:
instance GenUnchecked Prime where genUnchecked = Prime <$> arbitrary
instance GenValid Prime where genValid = Prime <$> (oneof [ pure 2 , ((\y -> 2 * abs y + 1) <$> arbitrary) `suchThat` isPrime) ])
Typical examples of tests involving validity could look as follows:
it "succeeds when given valid input" $ do forAllValid $ \input -> myFunction input `shouldSatisfy` isRight
it "produces valid output when it succeeds" $ do forAllUnchecked $ \input -> case myFunction input of Nothing -> return () -- Can happen Just output -> output `shouldSatisfy` isValid
Synopsis
- module Data.Validity
- class GValidSubtermsIncl f a where
- gValidSubtermsIncl :: f a -> [a]
- class GValidSubterms f a where
- gValidSubterms :: f a -> [a]
- class GValidRecursivelyShrink f where
- gValidRecursivelyShrink :: f a -> [f a]
- class GGenValid f where
- class GUncheckedSubtermsIncl f a where
- gUncheckedSubtermsIncl :: f a -> [a]
- class GUncheckedSubterms f a where
- gUncheckedSubterms :: f a -> [a]
- class GUncheckedRecursivelyShrink f where
- gUncheckedRecursivelyShrink :: f a -> [f a]
- class GGenUnchecked f where
- gGenUnchecked :: Gen (f a)
- class (Validity a, GenUnchecked a) => GenInvalid a where
- genInvalid :: Gen a
- shrinkInvalid :: a -> [a]
- class (Validity a, GenUnchecked a) => GenValid a where
- genValid :: Gen a
- shrinkValid :: a -> [a]
- class GenUnchecked a where
- genUnchecked :: Gen a
- shrinkUnchecked :: a -> [a]
- shrinkT2 :: (a -> [a]) -> (a, a) -> [(a, a)]
- shrinkT3 :: (a -> [a]) -> (a, a, a) -> [(a, a, a)]
- upTo :: Int -> Gen Int
- genSplit :: Int -> Gen (Int, Int)
- genSplit3 :: Int -> Gen (Int, Int, Int)
- genSplit4 :: Int -> Gen (Int, Int, Int, Int)
- genSplit5 :: Int -> Gen (Int, Int, Int, Int, Int)
- arbPartition :: Int -> Gen [Int]
- genListOf :: Gen a -> Gen [a]
- genericGenUnchecked :: (Generic a, GGenUnchecked (Rep a)) => Gen a
- genericShrinkUnchecked :: (Generic a, GUncheckedRecursivelyShrink (Rep a), GUncheckedSubterms (Rep a) a) => a -> [a]
- uncheckedRecursivelyShrink :: (Generic a, GUncheckedRecursivelyShrink (Rep a)) => a -> [a]
- uncheckedSubterms :: (Generic a, GUncheckedSubterms (Rep a) a) => a -> [a]
- genValidStructurally :: (Validity a, Generic a, GGenValid (Rep a)) => Gen a
- genValidStructurallyWithoutExtraChecking :: (Generic a, GGenValid (Rep a)) => Gen a
- shrinkValidStructurally :: (Validity a, Generic a, GValidRecursivelyShrink (Rep a), GValidSubterms (Rep a) a) => a -> [a]
- shrinkValidStructurallyWithoutExtraFiltering :: (Generic a, GValidRecursivelyShrink (Rep a), GValidSubterms (Rep a) a) => a -> [a]
- structurallyValidRecursivelyShrink :: (Generic a, GValidRecursivelyShrink (Rep a)) => a -> [a]
- structurallyValidSubterms :: (Generic a, GValidSubterms (Rep a) a) => a -> [a]
Documentation
module Data.Validity
class GValidSubtermsIncl f a where Source #
gValidSubtermsIncl :: f a -> [a] Source #
Instances
GValidSubtermsIncl (V1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: V1 a -> [a] Source # | |
GValidSubtermsIncl (U1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: U1 a -> [a] Source # | |
GValidSubtermsIncl (K1 i a :: Type -> Type) b Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: K1 i a b -> [b] Source # | |
GValidSubtermsIncl (K1 i a :: Type -> Type) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: K1 i a a -> [a] Source # | |
(GValidSubtermsIncl f a, GValidSubtermsIncl g a) => GValidSubtermsIncl (f :+: g) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: (f :+: g) a -> [a] Source # | |
(GValidSubtermsIncl f a, GValidSubtermsIncl g a) => GValidSubtermsIncl (f :*: g) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: (f :*: g) a -> [a] Source # | |
GValidSubtermsIncl f a => GValidSubtermsIncl (M1 i c f) a Source # | |
Defined in Data.GenValidity gValidSubtermsIncl :: M1 i c f a -> [a] Source # |
class GValidSubterms f a where Source #
gValidSubterms :: f a -> [a] Source #
Instances
GValidSubterms (V1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gValidSubterms :: V1 a -> [a] Source # | |
GValidSubterms (U1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gValidSubterms :: U1 a -> [a] Source # | |
GValidSubterms (K1 i a :: Type -> Type) b Source # | |
Defined in Data.GenValidity gValidSubterms :: K1 i a b -> [b] Source # | |
(GValidSubtermsIncl f a, GValidSubtermsIncl g a) => GValidSubterms (f :+: g) a Source # | |
Defined in Data.GenValidity gValidSubterms :: (f :+: g) a -> [a] Source # | |
(GValidSubtermsIncl f a, GValidSubtermsIncl g a) => GValidSubterms (f :*: g) a Source # | |
Defined in Data.GenValidity gValidSubterms :: (f :*: g) a -> [a] Source # | |
GValidSubterms f a => GValidSubterms (M1 i c f) a Source # | |
Defined in Data.GenValidity gValidSubterms :: M1 i c f a -> [a] Source # |
class GValidRecursivelyShrink f where Source #
gValidRecursivelyShrink :: f a -> [f a] Source #
Instances
GValidRecursivelyShrink (V1 :: Type -> Type) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: V1 a -> [V1 a] Source # | |
GValidRecursivelyShrink (U1 :: Type -> Type) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: U1 a -> [U1 a] Source # | |
GenValid a => GValidRecursivelyShrink (K1 i a :: Type -> Type) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: K1 i a a0 -> [K1 i a a0] Source # | |
(GValidRecursivelyShrink f, GValidRecursivelyShrink g) => GValidRecursivelyShrink (f :+: g) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: (f :+: g) a -> [(f :+: g) a] Source # | |
(GValidRecursivelyShrink f, GValidRecursivelyShrink g) => GValidRecursivelyShrink (f :*: g) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: (f :*: g) a -> [(f :*: g) a] Source # | |
GValidRecursivelyShrink f => GValidRecursivelyShrink (M1 i c f) Source # | |
Defined in Data.GenValidity gValidRecursivelyShrink :: M1 i c f a -> [M1 i c f a] Source # |
class GUncheckedSubtermsIncl f a where Source #
gUncheckedSubtermsIncl :: f a -> [a] Source #
Instances
class GUncheckedSubterms f a where Source #
gUncheckedSubterms :: f a -> [a] Source #
Instances
GUncheckedSubterms (V1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: V1 a -> [a] Source # | |
GUncheckedSubterms (U1 :: Type -> Type) a Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: U1 a -> [a] Source # | |
GUncheckedSubterms (K1 i a :: Type -> Type) b Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: K1 i a b -> [b] Source # | |
(GUncheckedSubtermsIncl f a, GUncheckedSubtermsIncl g a) => GUncheckedSubterms (f :+: g) a Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: (f :+: g) a -> [a] Source # | |
(GUncheckedSubtermsIncl f a, GUncheckedSubtermsIncl g a) => GUncheckedSubterms (f :*: g) a Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: (f :*: g) a -> [a] Source # | |
GUncheckedSubterms f a => GUncheckedSubterms (M1 i c f) a Source # | |
Defined in Data.GenValidity gUncheckedSubterms :: M1 i c f a -> [a] Source # |
class GUncheckedRecursivelyShrink f where Source #
gUncheckedRecursivelyShrink :: f a -> [f a] Source #
Instances
class GGenUnchecked f where Source #
gGenUnchecked :: Gen (f a) Source #
Instances
GGenUnchecked (U1 :: Type -> Type) Source # | |
Defined in Data.GenValidity gGenUnchecked :: Gen (U1 a) Source # | |
GenUnchecked a => GGenUnchecked (K1 i a :: Type -> Type) Source # | |
Defined in Data.GenValidity gGenUnchecked :: Gen (K1 i a a0) Source # | |
(GGenUnchecked a, GGenUnchecked b) => GGenUnchecked (a :+: b) Source # | |
Defined in Data.GenValidity gGenUnchecked :: Gen ((a :+: b) a0) Source # | |
(GGenUnchecked a, GGenUnchecked b) => GGenUnchecked (a :*: b) Source # | |
Defined in Data.GenValidity gGenUnchecked :: Gen ((a :*: b) a0) Source # | |
GGenUnchecked a => GGenUnchecked (M1 i c a) Source # | |
Defined in Data.GenValidity gGenUnchecked :: Gen (M1 i c a a0) Source # |
class (Validity a, GenUnchecked a) => GenInvalid a where Source #
A class of types for which invalid values can be generated.
Nothing
genInvalid :: Gen a Source #
shrinkInvalid :: a -> [a] Source #
Instances
GenInvalid a => GenInvalid [a] Source # | This instance ensures that the generated list contains at least one element
that satisfies |
Defined in Data.GenValidity genInvalid :: Gen [a] Source # shrinkInvalid :: [a] -> [[a]] Source # | |
GenInvalid a => GenInvalid (Maybe a) Source # | |
Defined in Data.GenValidity genInvalid :: Gen (Maybe a) Source # shrinkInvalid :: Maybe a -> [Maybe a] Source # | |
(Integral a, Num a, Ord a, GenValid a) => GenInvalid (Ratio a) Source # | |
Defined in Data.GenValidity genInvalid :: Gen (Ratio a) Source # shrinkInvalid :: Ratio a -> [Ratio a] Source # | |
GenInvalid a => GenInvalid (NonEmpty a) Source # | |
Defined in Data.GenValidity genInvalid :: Gen (NonEmpty a) Source # shrinkInvalid :: NonEmpty a -> [NonEmpty a] Source # | |
(GenInvalid a, GenInvalid b) => GenInvalid (Either a b) Source # | This instance ensures that the generated tupse contains at least one invalid element. The other element is unchecked. |
Defined in Data.GenValidity genInvalid :: Gen (Either a b) Source # shrinkInvalid :: Either a b -> [Either a b] Source # | |
(GenInvalid a, GenInvalid b) => GenInvalid (a, b) Source # | |
Defined in Data.GenValidity genInvalid :: Gen (a, b) Source # shrinkInvalid :: (a, b) -> [(a, b)] Source # | |
(GenInvalid a, GenInvalid b, GenInvalid c) => GenInvalid (a, b, c) Source # | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked. |
Defined in Data.GenValidity genInvalid :: Gen (a, b, c) Source # shrinkInvalid :: (a, b, c) -> [(a, b, c)] Source # | |
(GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d) => GenInvalid (a, b, c, d) Source # | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked. |
Defined in Data.GenValidity genInvalid :: Gen (a, b, c, d) Source # shrinkInvalid :: (a, b, c, d) -> [(a, b, c, d)] Source # | |
(GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d, GenInvalid e) => GenInvalid (a, b, c, d, e) Source # | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked. |
Defined in Data.GenValidity genInvalid :: Gen (a, b, c, d, e) Source # shrinkInvalid :: (a, b, c, d, e) -> [(a, b, c, d, e)] Source # |
class (Validity a, GenUnchecked a) => GenValid a where Source #
A class of types for which valid values can be generated.
If you also write Arbitrary
instances for GenValid
types, it may be
best to simply write arbitrary = genValid
.
Nothing
shrinkValid :: a -> [a] Source #
Shrink a valid value.
It is important that this shrinking function only shrinks values to valid values.
If shrinkValid
ever shrinks a value to an invalid value, the test that is being shrunk for
might fail for a different reason than for the reason that it originally failed.
This would lead to very confusing error messages.
Instances
class GenUnchecked a where Source #
A class of types for which truly arbitrary values can be generated.
Automatic instances with Generic
An instance of this class can be made automatically if the type in question
has a Generic
instance. This instance will try to use genUnchecked
to
generate all structural sub-parts of the value that is being generated.
Example:
{-# LANGUAGE DeriveGeneric #-} data MyType = MyType Rational String deriving (Show, Eq, Generic) instance GenUnchecked MyType
generates something like:
instance GenUnchecked MyType where genUnchecked = MyType <$> genUnchecked <*> genUnchecked
Nothing
genUnchecked :: Gen a Source #
genUnchecked :: (Generic a, GGenUnchecked (Rep a)) => Gen a Source #
shrinkUnchecked :: a -> [a] Source #
shrinkUnchecked :: (Generic a, GUncheckedRecursivelyShrink (Rep a), GUncheckedSubterms (Rep a) a) => a -> [a] Source #
Instances
genSplit :: Int -> Gen (Int, Int) Source #
'genSplit a' generates a tuple '(b, c)' such that 'b + c' equals a
.
genSplit3 :: Int -> Gen (Int, Int, Int) Source #
'genSplit3 a' generates a triple '(b, c, d)' such that 'b + c + d' equals a
.
genSplit4 :: Int -> Gen (Int, Int, Int, Int) Source #
'genSplit4 a' generates a quadruple '(b, c, d, e)' such that 'b + c + d + e' equals a
.
genSplit5 :: Int -> Gen (Int, Int, Int, Int, Int) Source #
'genSplit5 a' generates a quadruple '(b, c, d, e, f)' such that 'b + c + d + e + f' equals a
.
arbPartition :: Int -> Gen [Int] Source #
'arbPartition n' generates a list ls
such that 'sum ls' equals n
.
genListOf :: Gen a -> Gen [a] Source #
A version of listOf
that takes size into account more accurately.
genericGenUnchecked :: (Generic a, GGenUnchecked (Rep a)) => Gen a Source #
genericShrinkUnchecked :: (Generic a, GUncheckedRecursivelyShrink (Rep a), GUncheckedSubterms (Rep a) a) => a -> [a] Source #
Shrink a term to any of its immediate subterms, and also recursively shrink all subterms.
uncheckedRecursivelyShrink :: (Generic a, GUncheckedRecursivelyShrink (Rep a)) => a -> [a] Source #
Recursively shrink all immediate uncheckedSubterms.
uncheckedSubterms :: (Generic a, GUncheckedSubterms (Rep a) a) => a -> [a] Source #
All immediate uncheckedSubterms of a term.
shrinkValidStructurally :: (Validity a, Generic a, GValidRecursivelyShrink (Rep a), GValidSubterms (Rep a) a) => a -> [a] Source #
Shrink a term to any of its immediate valid subterms, and also recursively shrink all subterms.
shrinkValidStructurallyWithoutExtraFiltering :: (Generic a, GValidRecursivelyShrink (Rep a), GValidSubterms (Rep a) a) => a -> [a] Source #
structurallyValidRecursivelyShrink :: (Generic a, GValidRecursivelyShrink (Rep a)) => a -> [a] Source #
Recursively shrink all immediate structurally valid subterms.
structurallyValidSubterms :: (Generic a, GValidSubterms (Rep a) a) => a -> [a] Source #
All immediate validSubterms of a term.