packages feed

lawful-classes-hedgehog 0.1.1.1 → 0.1.2.0

raw patch · 4 files changed

+119/−2 lines, 4 filesdep +lawful-classes-hedgehogdep +mtldep +tasty-expected-failurePVP ok

version bump matches the API change (PVP)

Dependencies added: lawful-classes-hedgehog, mtl, tasty-expected-failure, transformers

API changes (from Hackage documentation)

+ Test.Lawful.Hedgehog: forAll :: (MonadTrans t, Monad m, Show a, HasCallStack) => Gen a -> t (PropertyT m) a
+ Test.Lawful.Hedgehog: forAllShow :: (MonadTrans t, Monad m, HasCallStack) => (a -> String) -> Gen a -> t (PropertyT m) a

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for lawful-classes-hedgehog +## 0.1.2.0 -- 2023-02-02++* Add `Test.Lawful.Hedgehog.forAll(Show)`.+ ## 0.1.1.1 -- 2023-02-01  * Support GHC 9.2.4 / base 4.16.3.0.
lawful-classes-hedgehog.cabal view
@@ -1,6 +1,6 @@ cabal-version:   3.0 name:            lawful-classes-hedgehog-version:         0.1.1.1+version:         0.1.2.0 synopsis:        Hedgehog support for lawful-classes description:   Support code to check @lawful-classes@ laws using Hedgehog and,@@ -41,6 +41,23 @@     , lawful-classes-types  ^>=0.1.0.0     , tasty                 ^>=1.4.3     , tasty-hedgehog        ^>=1.4.0.0+    , transformers          ^>=0.5.6.2    hs-source-dirs:   src   default-language: Haskell2010++test-suite lawful-classes-hedgehog-test+  import:           warnings+  default-language: Haskell2010+  type:             exitcode-stdio-1.0+  hs-source-dirs:   test+  main-is:          Main.hs+  build-depends:+    , base                     ^>=4.14.3.0 || ^>=4.15.1.0 || ^>=4.16.3.0 || ^>=4.17.0.0+    , hedgehog                 ^>=1.2+    , lawful-classes-hedgehog  ^>=0.1.2.0+    , lawful-classes-types     ^>=0.1.0.0+    , mtl                      ^>=2.2.2+    , tasty                    ^>=1.4.3+    , tasty-expected-failure   ^>=0.12.3+    , transformers             ^>=0.5.6.2
src/Test/Lawful/Hedgehog.hs view
@@ -15,12 +15,19 @@     testLaws,     testLawsWith, +    -- * Utilities+    forAll,+    forAllShow,+     -- * Plumbing     toProperty,   ) where -import Hedgehog (Property, PropertyT, assert, discard, evalM, property)+import Control.Monad.Trans.Class (MonadTrans, lift)+import GHC.Stack (HasCallStack, withFrozenCallStack)+import Hedgehog (Gen, Property, PropertyT, assert, discard, evalM, property)+import qualified Hedgehog as H import Test.Lawful.Types (Law, Laws) import Test.Tasty (TestName, TestTree, testGroup) import Test.Tasty.Hedgehog (testProperty)@@ -46,3 +53,22 @@ -- @since 0.1.1.0 testLawsWith :: (Property -> Property) -> TestName -> (forall a. m a -> PropertyT IO a) -> Laws m -> TestTree testLawsWith fn name run laws = testGroup name [testProperty n (fn $ toProperty run l) | (n, l) <- laws]++-- | Lifted version of 'H.forAll'.+--+-- This can be used to easily create generators for laws which need them.+--+-- @since 0.1.2.0+forAll :: (MonadTrans t, Monad m, Show a, HasCallStack) => Gen a -> t (PropertyT m) a+forAll gen = withFrozenCallStack $ lift (H.forAll gen)++-- | Lifted version of 'H.forAllWith'.+--+-- Like 'forAll', but for types without a 'Show' instance (or, for which+-- another stringification functions but 'show' should be used).+--+-- This can be used to earily create generators for laws which need them.+--+-- @since 0.1.2.0+forAllShow :: (MonadTrans t, Monad m, HasCallStack) => (a -> String) -> Gen a -> t (PropertyT m) a+forAllShow shw gen = withFrozenCallStack $ lift (H.forAllWith shw gen)
+ test/Main.hs view
@@ -0,0 +1,70 @@+module Main (main) where++import Control.Monad.State (evalState)+import Control.Monad.State.Class (MonadState, get, put)+import Control.Monad.Trans.State (evalStateT)+import Hedgehog (withTests)+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import Test.Lawful.Hedgehog (forAll, forAllShow, testLaws, testLawsWith)+import Test.Lawful.Types (Laws, assert, discard)+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.ExpectedFailure (expectFailBecause)++main :: IO ()+main = defaultMain tests++monadStateLaws :: (MonadState s m, Eq s) => m s -> Laws m+monadStateLaws gen =+  [ ( "get returns what was put",+      do+        a0 <- get+        a <- gen++        if a == a0+          then discard+          else do+            put a+            a' <- get+            assert $ a' == a+    )+  ]++newtype NoShow = NoShow Int+  deriving (Eq)++tests :: TestTree+tests =+  testGroup+    "lawful-classes-hedgehog"+    [ testGroup+        "StateT Int"+        [ testLaws+            "monadStateLaws"+            (`evalStateT` (0 :: Int))+            (monadStateLaws $ forAll $ Gen.integral Range.linearBounded)+        ],+      testGroup+        "StateT NoShow"+        [ testLaws+            "monadStateLaws"+            (`evalStateT` NoShow 0)+            (monadStateLaws (forAllShow (\(NoShow _) -> "NoShow") (NoShow <$> Gen.integral Range.linearBounded)))+        ],+      testGroup+        "StateT ()"+        [ expectFailBecause "() has only one possible value" $+            testLaws+              "monadStateLaws"+              (`evalStateT` ())+              (monadStateLaws $ forAll $ pure ())+        ],+      testGroup+        "State Int"+        [ testLawsWith+            (withTests 1)+            "monadStateLaws"+            (pure . flip evalState (0 :: Int))+            (monadStateLaws $ pure 1)+        ]+    ]