quickcheck-property-monad 0.1 → 0.2
raw patch · 3 files changed
+111/−58 lines, 3 filesdep ~QuickCheckdep ~basedep ~directory
Dependency ranges changed: QuickCheck, base, directory, doctest, either, filepath, transformers
Files
- LICENSE +1/−1
- quickcheck-property-monad.cabal +44/−49
- src/Test/QuickCheck/Property/Monad.hs +66/−8
LICENSE view
@@ -1,4 +1,4 @@-Copyright 2013 Benno Fünfstück+Copyright 2013-2014 Benno Fünfstück All rights reserved.
quickcheck-property-monad.cabal view
@@ -1,52 +1,47 @@-name: quickcheck-property-monad-version: 0.1-license: BSD3-cabal-version: >= 1.10-license-file: LICENSE-author: Benno Fünfstück-maintainer: Benno Fünfstück <benno.fuenfstueck@gmail.com>-stability: experimental-homepage: http://github.com/bennofs/quickcheck-property-monad/-bug-reports: http://github.com/bennofs/quickcheck-property-monad/issues-copyright: Copyright (C) 2013 Benno Fünfstück-synopsis: quickcheck-property-monad-description: quickcheck-property-monad-build-type: Custom-category: Testing--extra-source-files:- .ghci- .gitignore- .travis.yml- .vim.custom- README.md-+name: quickcheck-property-monad+version: 0.2+cabal-version: >=1.10+build-type: Custom+license: BSD3+license-file: LICENSE+copyright: Copyright (C) 2013-2014 Benno Fünfstück+maintainer: Benno Fünfstück <benno.fuenfstueck@gmail.com>+stability: experimental+homepage: http://github.com/bennofs/quickcheck-property-monad/+bug-reports: http://github.com/bennofs/quickcheck-property-monad/issues+synopsis: quickcheck-property-monad+description: quickcheck-property-monad+category: Testing+author: Benno Fünfstück+data-dir: ""+extra-source-files: .ghci .gitignore .travis.yml .vim.custom+ README.md+ source-repository head- type: git- location: https://github.com/bennofs/quickcheck-property-monad.git-+ type: git+ location: https://github.com/bennofs/quickcheck-property-monad.git+ library- hs-source-dirs: src- default-language: Haskell2010- ghc-options: -Wall- build-depends:- base >= 4.4 && < 5- , either- , transformers- , QuickCheck- exposed-modules:- Test.QuickCheck.Property.Monad-+ build-depends: base >=4.5 && <4.8, either >=4.1.1 && <4.2,+ transformers >=0.3.0.0 && <0.4, QuickCheck >=2.5.1.1 && <2.8+ exposed-modules: Test.QuickCheck.Property.Monad+ exposed: True+ buildable: True+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall+ test-suite doctests- type: exitcode-stdio-1.0- main-is: doctests.hs- default-language: Haskell2010- build-depends:- base- , directory >= 1.0- , doctest >= 0.9.1- , filepath- ghc-options: -Wall -threaded- if impl(ghc<7.6.1)- ghc-options: -Werror- hs-source-dirs: tests+ build-depends: base >=4.5 && <4.8, directory >=1.1.0.2 && <1.3,+ doctest >=0.9.11 && <0.10, filepath >=1.3.0.0 && <1.4+ + if impl(ghc <7.6.1)+ buildable: True+ ghc-options: -Werror+ type: exitcode-stdio-1.0+ main-is: doctests.hs+ buildable: True+ default-language: Haskell2010+ hs-source-dirs: tests+ ghc-options: -Wall -threaded+
src/Test/QuickCheck/Property/Monad.hs view
@@ -1,10 +1,14 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | Tutorial: <http://github.com/bennofs/quickcheck-property-monad/tree/master/README.md>+--+-- Note about the examples: The examples use a "-" in place of the empty line. This is required in order for doctest+-- to work. module Test.QuickCheck.Property.Monad ( PropM() , assert , failWith- , generate+ , gen , logMessage , logMessageLn ) where@@ -17,35 +21,89 @@ import Test.QuickCheck.Gen import Test.QuickCheck.Property +{- $setup+>>> :set -XNoMonomorphismRestriction+>>> import Test.QuickCheck (quickCheckWithResult, stdArgs, chatty, output, replay)+>>> import Test.QuickCheck.Random (mkQCGen)+>>> let transformEmpty "" = "-"; transformEmpty x = x+>>> let quickCheck = quickCheckWithResult (stdArgs { chatty = False, replay = Just (mkQCGen 42, 13) }) >=> putStr . unlines . map transformEmpty . lines . output+-}++#if !MIN_VERSION_QuickCheck(2,7,0)+counterexample :: Testable prop => String -> prop -> Property+counterexample = printTestCase+#endif+ -- | PropM is a monad for writing properties that depend on random -- data. This is especially useful if you have many invariants for -- your data and cannot simply write an 'Arbitrary' instance.+--+-- You can use a @PropM a@ as a QuickCheck Testable if @a@ is Testable. For example,+-- you can use @PropM Bool@ as a Testable property:+--+-- >>> quickCheck (return True :: PropM Bool)+-- +++ OK, passed 100 tests.+--+-- >>> quickCheck (return False :: PropM Bool)+-- *** Failed! Falsifiable (after 1 test):+-- - newtype PropM a = PropM (EitherT String (WriterT String Gen) a) deriving (Functor, Applicative, Alternative, Monad, MonadPlus) instance Testable a => Testable (PropM a) where- property (PropM m) = property $ do- (r,w) <- runWriterT $ runEitherT m- case r of- Right r' -> return $ property r'- Left err -> return $ printTestCase (w ++ "\n" ++ err) $ property False+ property (PropM m) = property $ fmap (counterexample . snd <*> makeProperty . fst) $ runWriterT $ runEitherT m where+ makeProperty (Right r) = property r+ makeProperty (Left err) = counterexample err $ property False -- | Assert that a certain condition is true. If the condition is false, fail with the -- given error message.+--+-- Examples:+--+-- >>> quickCheck $ assert "True is True!" True >> return True+-- +++ OK, passed 100 tests.+--+-- >>> quickCheck $ assert "False is True!" False >> return True+-- *** Failed! Falsifiable (after 1 test):+-- -+-- Assertion failed: False is True! assert :: String -> Bool -> PropM () assert err cond = unless cond $ failWith $ "Assertion failed: " ++ err -- | Fail with the given error message.+--+-- Example:+--+-- >>> quickCheck $ failWith "Something horrible happened" >> return True+-- *** Failed! Falsifiable (after 1 test):+-- -+-- Something horrible happened failWith :: String -> PropM () failWith err = PropM $ left err -- | Use the given generator to generate a value.-generate :: Gen a -> PropM a-generate = PropM . lift . lift+--+-- Examples:+--+-- >>> quickCheck $ fmap (`elem` [0..5]) $ gen (elements [0..5])+-- +++ OK, passed 100 tests.+--+-- >>> quickCheck $ fmap (> 0) $ gen (choose (0,1))+-- *** Failed! Falsifiable (after 2 tests):+-- -+gen :: Gen a -> PropM a+gen = PropM . lift . lift -- | Log a message that will be printed when the test case fails. logMessage :: String -> PropM () logMessage = PropM . lift . tell -- | Like 'logMessage' but appends a line break after the message.+--+-- Example:+--+-- >>> quickCheck $ gen (choose (0,1)) >>= \x -> logMessageLn ("Chosen: " ++ show x) >> return (x > 0)+-- *** Failed! Falsifiable (after 2 tests):+-- Chosen: 0+-- - logMessageLn :: String -> PropM () logMessageLn = logMessage . (++ "\n")