packages feed

ImpSpec 0.1.0.0 → 0.2.0.0

raw patch · 5 files changed

+135/−88 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Test.ImpSpec: arbitrary :: (Arbitrary a, MonadGen m) => m a
- Test.ImpSpec: askStatefulGen :: (HasStatefulGen g m, MonadReader g m) => m g
- Test.ImpSpec: assertBool :: (HasCallStack, MonadIO m) => String -> Bool -> m ()
- Test.ImpSpec: assertColorFailure :: (HasCallStack, MonadIO m) => String -> m a
- Test.ImpSpec: assertFailure :: (HasCallStack, MonadIO m) => String -> m a
- Test.ImpSpec: class HasGenEnv env g | env -> g
- Test.ImpSpec: class StatefulGen g m => HasStatefulGen g m | m -> g
- Test.ImpSpec: expectJust :: (HasCallStack, MonadIO m) => Maybe a -> m a
- Test.ImpSpec: expectJustDeep :: (HasCallStack, NFData a, MonadIO m) => Maybe a -> m a
- Test.ImpSpec: expectJustDeep_ :: (HasCallStack, NFData a, MonadIO m) => Maybe a -> m ()
- Test.ImpSpec: expectLeft :: (HasCallStack, Show b, MonadIO m) => Either a b -> m a
- Test.ImpSpec: expectLeftDeep :: (HasCallStack, NFData a, Show b, MonadIO m) => Either a b -> m a
- Test.ImpSpec: expectLeftDeep_ :: (HasCallStack, NFData a, Show b, MonadIO m) => Either a b -> m ()
- Test.ImpSpec: expectNothing :: (HasCallStack, Show a, MonadIO m) => Maybe a -> m ()
- Test.ImpSpec: expectRight :: (HasCallStack, Show a, MonadIO m) => Either a b -> m b
- Test.ImpSpec: expectRightDeep :: (HasCallStack, Show a, NFData b, MonadIO m) => Either a b -> m b
- Test.ImpSpec: expectRightDeep_ :: (HasCallStack, Show a, NFData b, MonadIO m) => Either a b -> m ()
- Test.ImpSpec: expectationFailure :: (HasCallStack, MonadIO m) => String -> m ()
- Test.ImpSpec: getGenEnv :: HasGenEnv env g => env -> g
- Test.ImpSpec: impSpecConfig :: Config
- Test.ImpSpec: impSpecMain :: Spec -> IO ()
- Test.ImpSpec: impSpecMainWithConfig :: Config -> Spec -> IO ()
- Test.ImpSpec: infix 1 `shouldBeLeft`
- Test.ImpSpec: io :: IO a -> IO a
- Test.ImpSpec: shouldBe :: (HasCallStack, MonadIO m, Show a, Eq a) => a -> a -> m ()
- Test.ImpSpec: shouldBeJust :: (HasCallStack, Show a, Eq a, MonadIO m) => Maybe a -> a -> m ()
- Test.ImpSpec: shouldBeLeft :: (HasCallStack, Show a, Eq a, Show b, MonadIO m) => Either a b -> a -> m ()
- Test.ImpSpec: shouldBeRight :: (HasCallStack, Show a, Show b, Eq b, MonadIO m) => Either a b -> b -> m ()
- Test.ImpSpec: shouldContain :: (HasCallStack, MonadIO m, Show a, Eq a) => [a] -> [a] -> m ()
- Test.ImpSpec: shouldEndWith :: (HasCallStack, MonadIO m, Show a, Eq a) => [a] -> [a] -> m ()
- Test.ImpSpec: shouldMatchList :: (HasCallStack, MonadIO m, Show a, Eq a) => [a] -> [a] -> m ()
- Test.ImpSpec: shouldNotBe :: (HasCallStack, MonadIO m, Show a, Eq a) => a -> a -> m ()
- Test.ImpSpec: shouldNotContain :: (HasCallStack, MonadIO m, Show a, Eq a) => [a] -> [a] -> m ()
- Test.ImpSpec: shouldNotReturn :: (HasCallStack, MonadIO m, Show a, Eq a) => m a -> a -> m ()
- Test.ImpSpec: shouldNotSatisfy :: (HasCallStack, MonadIO m, Show a) => a -> (a -> Bool) -> m ()
- Test.ImpSpec: shouldReturn :: (HasCallStack, MonadIO m, Show a, Eq a) => m a -> a -> m ()
- Test.ImpSpec: shouldSatisfy :: (HasCallStack, MonadIO m, Show a) => a -> (a -> Bool) -> m ()
- Test.ImpSpec: shouldStartWith :: (HasCallStack, MonadIO m, Show a, Eq a) => [a] -> [a] -> m ()
- Test.ImpSpec: shouldThrow :: (HasCallStack, Exception e, MonadUnliftIO m) => m a -> Selector e -> m ()
- Test.ImpSpec: type Selector a = a -> Bool
- Test.ImpSpec: uniformByteStringM :: HasStatefulGen a m => Int -> m ByteString
- Test.ImpSpec: uniformListM :: (HasStatefulGen g m, Uniform a) => Int -> m [a]
- Test.ImpSpec: uniformListRM :: (HasStatefulGen g m, UniformRange a) => (a, a) -> Int -> m [a]
- Test.ImpSpec: uniformM :: (HasStatefulGen g m, Uniform a) => m a
- Test.ImpSpec: uniformRM :: (HasStatefulGen g m, UniformRange a) => (a, a) -> m a
- Test.ImpSpec: uniformShortByteStringM :: HasStatefulGen a m => Int -> m ShortByteString
+ Test.ImpSpec: ($dmimpInitIO) :: (ImpSpec t, ImpSpecEnv t ~ Proxy t, ImpSpecState t ~ Proxy t) => QCGen -> IO (ImpInit t)
+ Test.ImpSpec: type family ImpSpecEnv t = (r :: Type) | r -> t
+ Test.ImpSpec.Random: ($dmaskStatefulGen) :: (HasStatefulGen g m, MonadReader g m) => m g
- Test.ImpSpec: impInitIO :: (ImpSpec t, ImpSpecEnv t ~ Proxy t, ImpSpecState t ~ Proxy t) => QCGen -> IO (ImpInit t)
+ Test.ImpSpec: impInitIO :: ImpSpec t => QCGen -> IO (ImpInit t)
- Test.ImpSpec.Random: askStatefulGen :: (HasStatefulGen g m, MonadReader g m) => m g
+ Test.ImpSpec.Random: askStatefulGen :: HasStatefulGen g m => m g
- Test.ImpSpec.Random: class StatefulGen g m => HasStatefulGen g m | m -> g
+ Test.ImpSpec.Random: class StatefulGen g m => HasStatefulGen g (m :: Type -> Type) | m -> g
- Test.ImpSpec.Random: uniformListM :: (HasStatefulGen g m, Uniform a) => Int -> m [a]
+ Test.ImpSpec.Random: uniformListM :: forall a g m. (HasStatefulGen g m, Uniform a) => Int -> m [a]
- Test.ImpSpec.Random: uniformListRM :: (HasStatefulGen g m, UniformRange a) => (a, a) -> Int -> m [a]
+ Test.ImpSpec.Random: uniformListRM :: forall a g m. (HasStatefulGen g m, UniformRange a) => (a, a) -> Int -> m [a]
- Test.ImpSpec.Random: uniformM :: (HasStatefulGen g m, Uniform a) => m a
+ Test.ImpSpec.Random: uniformM :: forall a g m. (HasStatefulGen g m, Uniform a) => m a
- Test.ImpSpec.Random: uniformRM :: (HasStatefulGen g m, UniformRange a) => (a, a) -> m a
+ Test.ImpSpec.Random: uniformRM :: forall a g m. (HasStatefulGen g m, UniformRange a) => (a, a) -> m a

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Version history for `ImpSpec` +## 0.2.0.0++* Add explicit `forall` for `uniformM`, `uniformRM`, `uniformListM`, `uniformListRM` and `arbitrary`+ ## 0.1.0.0 -*+* Initital release
ImpSpec.cabal view
@@ -1,79 +1,93 @@-cabal-version:      1.18-name:               ImpSpec-version:            0.1.0.0-license:            Apache-2.0-license-file:       LICENSE-maintainer:         operations@iohk.io-author:             IOHK-homepage:           https://github.com/input-output-hk/ImpSpec+cabal-version: 2.4+name: ImpSpec+version: 0.2.0.0+license: Apache-2.0+license-file: LICENSE+maintainer: operations@iohk.io+author: IOHK+homepage: https://github.com/input-output-hk/ImpSpec synopsis:-    Imperative approach to testing stateful applications. ImpSpec is build on top of HSpec and QuickCheck+  Imperative approach to testing stateful applications.+  ImpSpec is built on top of HSpec and QuickCheck.+ description:-    Let a little imp help you discover all the bugs in your stateful Haskell program.-category:           Control-build-type:         Simple-extra-doc-files:    CHANGELOG.md+  Let a little imp help you discover all the bugs in your stateful Haskell program.++category: Testing+build-type: Simple+extra-doc-files: CHANGELOG.md extra-source-files: README.md-tested-with:        GHC == 8.2.2-                  , GHC == 8.4.4-                  , GHC == 8.6.5-                  , GHC == 8.8.4-                  , GHC == 8.10.7-                  , GHC == 9.0.2-                  , GHC == 9.2.8-                  , GHC == 9.4.8-                  , GHC == 9.6.6-                  , GHC == 9.8.2-                  , GHC == 9.10.1+tested-with:+  ghc ==8.2.2+  ghc ==8.4.4+  ghc ==8.6.5+  ghc ==8.8.4+  ghc ==8.10.7+  ghc ==9.0.2+  ghc ==9.2.8+  ghc ==9.4.8+  ghc ==9.6.6+  ghc ==9.8.2+  ghc ==9.10.3  source-repository head-    type:     git-    location: https://github.com/intersectmbo/cardano-ledger-    subdir:   libs/ImpSpec+  type: git+  location: https://github.com/input-output-hk/ImpSpec  library-    exposed-modules:-        Test.ImpSpec-        Test.ImpSpec.Expectations-        Test.ImpSpec.Expectations.Lifted-        Test.ImpSpec.Main-        Test.ImpSpec.Random+  exposed-modules:+    Test.ImpSpec+    Test.ImpSpec.Expectations+    Test.ImpSpec.Expectations.Lifted+    Test.ImpSpec.Main+    Test.ImpSpec.Random -    hs-source-dirs:   src-    other-modules:    Test.ImpSpec.Internal-    default-language: Haskell2010-    ghc-options:-        -Wall -Wcompat -Wincomplete-record-updates-        -Wincomplete-uni-patterns -Wredundant-constraints+  hs-source-dirs: src+  other-modules: Test.ImpSpec.Internal+  default-language: Haskell2010+  ghc-options:+    -Wall+    -Wcompat+    -Wincomplete-record-updates+    -Wincomplete-uni-patterns+    -Wredundant-constraints -    build-depends:-        base >=4.9 && <5,-        bytestring,-        deepseq,-        hspec,-        hspec-core >=2.11,-        hspec-expectations-lifted,-        HUnit,-        mtl,-        QuickCheck,-        quickcheck-transformer,-        prettyprinter >=1.7,-        prettyprinter-ansi-terminal >=1.1.2,-        random >=1.2,-        text,-        unliftio+  build-depends:+    HUnit,+    QuickCheck,+    base >=4.9 && <5,+    bytestring,+    deepseq,+    hspec,+    hspec-core >=2.11,+    hspec-expectations-lifted,+    mtl,+    prettyprinter >=1.7,+    prettyprinter-ansi-terminal >=1.1.2,+    quickcheck-transformer,+    random >=1.2,+    text,+    unliftio,  test-suite tests-    type:             exitcode-stdio-1.0-    main-is:          Main.hs-    hs-source-dirs:   test-    other-modules:    Test.Suite.ImpSpec-    default-language: Haskell2010-    ghc-options:-        -Wall -Wcompat -Wincomplete-record-updates-        -Wincomplete-uni-patterns -Wredundant-constraints-        -threaded -rtsopts+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs: test+  other-modules: Test.Suite.ImpSpec+  default-language: Haskell2010+  ghc-options:+    -Wall+    -Wcompat+    -Wincomplete-record-updates+    -Wincomplete-uni-patterns+    -Wredundant-constraints+    -threaded+    -rtsopts -    build-depends:-        base,-        ImpSpec+  build-depends:+    ImpSpec,+    base,++source-repository head+  type: git+  location: https://github.com/input-output-hk/ImpSpec
README.md view
@@ -17,10 +17,10 @@ |:--------------:|:---------:|:-------:|:-------:|:---:| | [![Build Status][GA-badge]][GA-link] | [![Coverage Status][Coveralls-badge]][Coveralls-link] | [![Hackage][Hackage-badge]][Hackage-link] | [![Nightly][Nightly-badge]][Nightly-link] | [![LTS][LTS-badge]][LTS-link] -[GA-badge]: https://github.com/lehins/ImpSpec/workflows/CI/badge.svg-[GA-link]: https://github.com/lehins/ImpSpec/actions-[Coveralls-badge]: https://coveralls.io/repos/github/lehins/ImpSpec/badge.svg?branch=master-[Coveralls-link]: https://coveralls.io/github/lehins/ImpSpec?branch=master+[GA-badge]: https://github.com/input-output-hk/ImpSpec/workflows/CI/badge.svg+[GA-link]: https://github.com/input-output-hk/ImpSpec/actions+[Coveralls-badge]: https://coveralls.io/repos/github/input-output-hk/ImpSpec/badge.svg?branch=master+[Coveralls-link]: https://coveralls.io/github/input-output-hk/ImpSpec?branch=master [Hackage-badge]: https://img.shields.io/hackage/v/ImpSpec.svg [Hackage-link]: https://hackage.haskell.org/package/ImpSpec [Nightly-badge]: https://www.stackage.org/package/ImpSpec/badge/nightly
src/Test/ImpSpec/Internal.hs view
@@ -13,6 +13,9 @@ {-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}+#if MIN_VERSION_random(1,3,0) && !MIN_VERSION_QuickCheck(2,16,1)+{-# OPTIONS_GHC -Wno-orphans #-}+#endif  module Test.ImpSpec.Internal where @@ -39,7 +42,11 @@   vsep,  ) import Prettyprinter.Render.Terminal (AnsiStyle, Color (..), color, renderLazy)-import System.Random (randomR, split)+#if MIN_VERSION_random(1,3,0)+import System.Random (randomR, SplitGen (splitGen))+#else+import System.Random (randomR, RandomGen (split))+#endif import System.Random.Stateful (IOGenM, applyIOGen, newIOGenM) import Test.HUnit.Lang (FailureReason (..), HUnitFailure (..)) import Test.Hspec (Spec, SpecWith, beforeAll, beforeAllWith)@@ -68,6 +75,15 @@ import Data.Monoid ((<>)) #endif +#if !MIN_VERSION_random(1,3,0)+splitGen :: RandomGen g => g -> (g, g)+splitGen = split+#endif++#if MIN_VERSION_random(1,3,0) && !MIN_VERSION_QuickCheck(2,16,1)+deriving instance SplitGen QCGen+#endif+ data ImpState t = ImpState   { impStateSpecState :: !(ImpSpecState t)   , impStateLog :: !(Doc AnsiStyle)@@ -98,8 +114,11 @@   { impInitEnv :: ImpSpecEnv t   , impInitState :: ImpSpecState t   }+ deriving instance (Eq (ImpSpecEnv t), Eq (ImpSpecState t)) => Eq (ImpInit t)+ deriving instance (Ord (ImpSpecEnv t), Ord (ImpSpecState t)) => Ord (ImpInit t)+ deriving instance (Show (ImpSpecEnv t), Show (ImpSpecState t)) => Show (ImpInit t)  -- | Stores extra information about the failure of the unit test@@ -134,30 +153,30 @@  instance env ~ ImpSpecEnv t => MonadReader env (ImpM t) where   ask = impEnvSpecEnv <$> ImpM ask-  local f = ImpM . local (\e -> e{impEnvSpecEnv = f (impEnvSpecEnv e)}) . unImpM+  local f = ImpM . local (\e -> e {impEnvSpecEnv = f (impEnvSpecEnv e)}) . unImpM  instance Fail.MonadFail (ImpM t) where   fail = liftIO . assertFailure  instance s ~ ImpSpecState t => MonadState s (ImpM t) where   state f = do-    ImpEnv{impEnvStateRef} <- ImpM ask+    ImpEnv {impEnvStateRef} <- ImpM ask     curState <- readIORef impEnvStateRef     let !(result, !newSpecState) = f $ impStateSpecState curState-    writeIORef impEnvStateRef (curState{impStateSpecState = newSpecState})+    writeIORef impEnvStateRef (curState {impStateSpecState = newSpecState})     pure result   get = fmap impStateSpecState . readIORef . impEnvStateRef =<< ImpM ask  instance MonadGen (ImpM t) where   liftGen (MkGen f) = do     qcSize <- ImpM $ asks impEnvQCSize-    qcGen <- applyQCGen split+    qcGen <- applyQCGen splitGen     pure $ f qcGen qcSize   variant n action = do     applyQCGen $ \qcGen -> ((), integerVariant (toInteger n) qcGen)     action   sized f = ImpM (asks impEnvQCSize) >>= f-  resize n (ImpM f) = ImpM $ local (\env -> env{impEnvQCSize = n}) f+  resize n (ImpM f) = ImpM $ local (\env -> env {impEnvQCSize = n}) f   choose r = applyQCGen (randomR r)  instance HasStatefulGen (IOGenM QCGen) (ImpM t) where@@ -166,7 +185,7 @@ instance (ImpSpec t, Testable a) => Testable (ImpM t a) where   property m = property $ MkGen $ \qcGen qcSize ->     ioProperty $ do-      let (qcGen1, qcGen2) = split qcGen+      let (qcGen1, qcGen2) = splitGen qcGen       impInit <- impInitIO qcGen1       evalImpM (Just qcGen2) (Just qcSize) impInit m @@ -186,10 +205,10 @@           (r, testable, logs) <- evalImpM (fst <$> mQC) (snd <$> mQC) impInit $ do             t <- impTest x             qcSize <- ImpM $ asks impEnvQCSize-            qcGen <- applyQCGen split+            qcGen <- applyQCGen splitGen             logs <- getLogs             pure (Just (qcGen, qcSize), t, logs)-          let params' = params{paramsQuickCheckArgs = args{replay = r, chatty = False}}+          let params' = params {paramsQuickCheckArgs = args {replay = r, chatty = False}}           res <-             evaluateExample               (counterexample (ansiDocToString logs) testable)@@ -212,11 +231,11 @@ modifyLogs :: (Doc AnsiStyle -> Doc AnsiStyle) -> ImpM t () modifyLogs f = do   ref <- ImpM $ asks impEnvStateRef-  modifyIORef ref $ \s -> s{impStateLog = f (impStateLog s)}+  modifyIORef ref $ \s -> s {impStateLog = f (impStateLog s)}  -- | Override the QuickCheck generator using a fixed seed. impSetSeed :: Int -> ImpM t ()-impSetSeed seed = applyQCGen $ \_ -> ((), mkQCGen seed)+impSetSeed seed = applyQCGen $ const ((), mkQCGen seed)  evalImpGenM :: ImpSpec t => ImpInit t -> ImpM t b -> Gen (IO b) evalImpGenM impInit = fmap (fmap fst) . runImpGenM impInit@@ -253,7 +272,7 @@   ImpInit t ->   ImpM t b ->   IO (b, ImpState t)-runImpM mQCGen mQCSize ImpInit{impInitEnv, impInitState} action = do+runImpM mQCGen mQCSize ImpInit {impInitEnv, impInitState} action = do   let qcSize = fromMaybe 30 mQCSize       qcGen = fromMaybe (mkQCGen 2024) mQCGen   ioRef <-@@ -364,7 +383,7 @@ logWithCallStack callStack entry =   modifyLogs (<> stack <> line <> indent 2 entry <> line)   where-    prettySrcLoc' SrcLoc{srcLocModule, srcLocStartLine} =+    prettySrcLoc' SrcLoc {srcLocModule, srcLocStartLine} =       hcat         [ annotate (color c) d         | (c, d) <-
src/Test/ImpSpec/Random.hs view
@@ -1,9 +1,9 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} @@ -35,6 +35,7 @@   askStatefulGen = ReaderT (pure . getGenEnv)  uniformM ::+  forall a g m.   ( HasStatefulGen g m   , R.Uniform a   ) =>@@ -43,6 +44,7 @@ {-# INLINE uniformM #-}  uniformRM ::+  forall a g m.   ( HasStatefulGen g m   , R.UniformRange a   ) =>@@ -52,6 +54,7 @@ {-# INLINE uniformRM #-}  uniformListM ::+  forall a g m.   ( HasStatefulGen g m   , R.Uniform a   ) =>@@ -61,6 +64,7 @@ {-# INLINE uniformListM #-}  uniformListRM ::+  forall a g m.   (HasStatefulGen g m, R.UniformRange a) =>   (a, a) ->   Int ->@@ -73,9 +77,15 @@ {-# INLINE uniformByteStringM #-}  uniformShortByteStringM :: HasStatefulGen a m => Int -> m ShortByteString+#if MIN_VERSION_random(1,3,0)+uniformShortByteStringM n = askStatefulGen >>= R.uniformShortByteStringM n+#else uniformShortByteStringM n = askStatefulGen >>= R.uniformShortByteString n+#endif {-# INLINE uniformShortByteStringM #-}  -- | Lifted version of `QC.arbitrary`.-arbitrary :: (QC.Arbitrary a, MonadGen m) => m a+arbitrary ::+  forall a m.+  (QC.Arbitrary a, MonadGen m) => m a arbitrary = liftGen QC.arbitrary