quickcheck-property-comb 0.1.0.0 → 0.1.0.1
raw patch · 3 files changed
+89/−36 lines, 3 filesdep ~QuickCheck
Dependency ranges changed: QuickCheck
Files
- README.md +5/−6
- Test/QuickCheck/Property/Comb.hs +24/−22
- quickcheck-property-comb.cabal +60/−8
README.md view
@@ -1,16 +1,16 @@ quickcheck-property-comb ---------This is collection of combinators built on the Reader and Writer-Monads to allow for fast and painless Quickcheck property/invariant construction.+These are combinators, based on the Reader and Writer Monads, to allow for fast+and painless Quickcheck property/invariant construction. Why? ---- [Quickcheck](http://hackage.haskell.org/package/QuickCheck) is a tool used to-test cases based on constructed Properties,or essentially functions taking a+test cases based on constructed Properties, or essentially functions taking a data structure and returning a boolean True or False. However when running tests, the only way to document their failing case-is through is through labeling them after binding, e.g.: +is through labeling them after binding, e.g.: ```haskell inv1, inv2, inv3 :: Foo -> Bool @@ -25,8 +25,7 @@ This gets unwieldy fast as the complexity of the data-structure increases, so quickcheck-property-comb provides the following:- - A clean separation of composition of invariants and the creation - and documenting of those invariants for determining cause of failure.+ - Monadically unifies composition of invariants and the documenting of those invariants for determining cause of failure. - Effective diagnostics for invariants with changing post-conditions, leading to <b>faster cause-of-failure diagnosis</b>.
Test/QuickCheck/Property/Comb.hs view
@@ -1,41 +1,43 @@ -- TODO in some cases it may be useful to indent messages--- based on an invariant category above them+-- based on a documented "context" above them {-# LANGUAGE TupleSections, ScopedTypeVariables, GeneralizedNewtypeDeriving #-}-module Test.QuickCheck.Property.Comb where+module Test.QuickCheck.Property.Comb (+ cause, Inv, Invariants, doc, sat, satcomp, runInv, runInvariants+ ) where import Test.QuickCheck import Control.Monad.Writer import Control.Monad.Reader ---A Monad which collects related invariants on the input-type InvM i r = ReaderT i (Writer String) r-type Inv i = InvM i Bool+-- A Monad which collects related invariants on the input+type InvM c r = ReaderT c (Writer String) r+type Inv c = InvM c Bool -cause :: (Monad m) => ReaderT i m i+cause :: (Monad m) => ReaderT c m c cause = ask ---A Monad which collects distinct invariants on the input-type Invariants i = ReaderT i (Writer [Inv i]) ()+-- A Monad which collects invariants on the input+type Invariants c = ReaderT c (Writer [Inv c]) () doc :: String -> InvM r () doc = lift . tell -sat :: Inv i -> Invariants i-sat p = lift . tell $ (p:[])+sat :: Inv c -> Invariants c+sat p = lift . tell $ [p] -satcomp :: forall i i'. (i' -> i) -> Invariants i -> Invariants i'+satcomp :: forall c c'. (c' -> c) -> Invariants c -> Invariants c' satcomp f = mapReaderT toWriter . withReaderT f where- toWriter :: Writer [Inv i] () -> Writer [Inv i'] ()- toWriter orig = mapWriter (((),) . map toPredicate . snd) orig- toPredicate :: Inv i -> Inv i'- toPredicate orig = withReaderT f orig+ toWriter :: Writer [Inv c] () -> Writer [Inv c'] ()+ toWriter = mapWriter (((),) . map toPredicate . snd)+ toPredicate :: Inv c -> Inv c'+ toPredicate = withReaderT f -runInv :: (Show i) => i -> Inv i -> Property-runInv cause' rdr =- let (effect, msg) = runWriter . (runReaderT rdr) $ cause' in- printTestCase ("inv: " ++ if null msg then "unknown" else msg)+runInv :: (Show c) => c -> Inv c -> Property+runInv checked rdr =+ let (effect, msg) = runWriter . runReaderT rdr $ checked in+ printTestCase ("invariant: " ++ if null msg then "unknown" else msg) . property $ effect -runInvariants :: forall i. (Show i) => i -> Invariants i -> Property-runInvariants cause' preds =- conjoin . map (runInv cause') . execWriter . runReaderT preds $ cause'+runInvariants :: (Show c) => c -> Invariants c -> Property+runInvariants checked preds =+ conjoin . map (runInv checked) . execWriter . runReaderT preds $ checked
quickcheck-property-comb.cabal view
@@ -2,13 +2,65 @@ -- further documentation, see http://haskell.org/cabal/users-guide/ name: quickcheck-property-comb-version: 0.1.0.0-synopsis: Combinators for Quickcheck Property construction and Property diagnostics-description: This project aims to reduce the pain of composing- invariants/properties, and the documenting of those invariants for determining the cause- of failure. Additionally, it intends to provide effective diagnostics for- invariants with changing post-conditions, leading to faster cause-of-failure- diagnosis.+version: 0.1.0.1+synopsis: Combinators for Quickcheck Property construction and diagnostics+description: + These are simple monads that aim to reduce the pain of composing+ invariants/properties, and the documenting of those+ invariants for determining the cause of failure.+ Specifically, they provide a tool for effective diagnostic+ for invariants with changing post-conditions, leading to a+ faster cause-of-failure diagnosis.+ .+ Example case for invariants on a data structure "Consumers".+ .+ > data (Ord l) => Consumers l =+ > Consumers {+ > introduced :: S.Set l,+ > met :: M.Map (S.Set l) Bool,+ > disjoints :: Disjoints l+ > }+ >+ > introduced_in_disjoint :: Inv (Consumers l)+ > introduced_in_disjoint = do+ > doc "all at quantity are a singleton subset in disjoints"+ > subsets <- (map S.singleton) . S.toList . introduced <$> cause+ > disjoint_sets <- disjoints <$> cause+ > return . and . map ((flip S.member) disjoint_sets) $ subsets+ > + > disjoint_sizes :: Inv (Disjoints l)+ > disjoint_sizes = do+ > doc . unlines $+ > [ "the intersection of introduced and disjoints are the only allowed",+ > "singleton sets in disjoints"+ > ]+ > disjoints' <- cause + > -- Do the checking+ > return False+ >+ > disjoints_eq :: Inv (Disjoints l)+ > disjoints_eq = do+ > doc "disjoint sets are equal in size"+ > -- ..+ > return True+ >+ > disjoints_inv :: Invariants (Disjoints l)+ > disjoints_inv= do+ > sat disjoints_eq+ > sat disjoints_sizes+ > + > inv_consumers :: Invariants (Consumers l)+ > inv_consumers = do+ > satcomp disjoints disjoints_inv+ > satcomp met met_inv+ > sat introduced_in_disjoint+ . + And to run the Consumer invariant on generated cases: + .+ > prop_testedFunction :: Arg -> Property+ > prop_testedFunction arg = + > let consumers = testedFunction arg in+ > runInvariants consumers inv_consumers homepage: http://www.github.com/jfeltz/quickcheck-property-comb license: PublicDomain@@ -23,6 +75,6 @@ exposed-modules: Test.QuickCheck.Property.Comb -- other-modules: other-extensions: TupleSections, ScopedTypeVariables, GeneralizedNewtypeDeriving- build-depends: base >=4.5 && <4.6, QuickCheck >=2.5 && <2.6, mtl >=2.1 && <2.2+ build-depends: base >=4.5 && <4.6, QuickCheck >=2.5 && <=2.6, mtl >=2.1 && <2.2 hs-source-dirs: ./ default-language: Haskell2010