packages feed

hspec-expectations-lens 0.2.0.0 → 0.2.1.0

raw patch · 5 files changed

+217/−43 lines, 5 files

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+0.2.1.0+=======++  * Add a `shouldPerform` expectation+  * Improve expectations' error messages+ 0.2.0.0 ======= 
+ README.lhs view
@@ -0,0 +1,144 @@+hspec-expectations-lens+=======================+[![Hackage](https://budueba.com/hackage/hspec-expectations-lens)](http://hackage.haskell.org/package/hspec-expectations-lens)+[![Build Status](https://secure.travis-ci.org/supki/hspec-expectations-lens.png?branch=master)](http://travis-ci.org/supki/hspec-expectations-lens)++hspec-expectations-lens is a set of expectations for [Hspec][hspec]+with a [lens][lens]-compatible interface++This README is a literate haskell file which contains a Hspec spec.+You can run it with `runhaskell`; result is something akin to:+++```shell+% runhaskell README.lhs++shouldHave+  - checks targets exist+  - looks as deep into structure as you want+  - replaces 'shouldBe'+  - checks a bigger part of the structure for equality+  - checks the whole structure for equality++shouldNotHave+  - is the opposite of 'shouldHave'++shouldView+  - gets a single target verbatim+  - combines multiple targets using Monoid instance++shouldList+  - combines multiple targets into list++shouldPreview+  - gets the first target++shouldPerform+  - performs an action and gets the first target++shouldThrow+  - looks into the 'error' call+  - looks into the division by zero+```++Expectations+------------++We start with pragmas, module declaration, and imports we use later.++> {-# LANGUAGE ExtendedDefaultRules #-} -- this is only neccessary because we don't like annotations+>+> module Main (main) where+>+> import Control.Lens+> import Data.List.Lens+> import Control.Exception (evaluate)+> import Control.Exception.Lens (_ErrorCall, _DivideByZero)+> import Test.Hspec.Lens+>+> main :: IO ()+> main = hspec $ do++hspec-expectations-lens expectations form several groups. First one contains `shouldHave`+and `shouldNotHave` combinators—they check whether a `Fold` you give them has (or doesn't have)+any targets in the structure.++>   describe "shouldHave" $ do+>     it "checks targets exist" $+>       Right (Just (Left 'a')) `shouldHave` _Right++We can look arbitrarily deep into the structure; for instance, `_Right._Just._Left`+would also work here:++>     it "looks as deep into structure as you want" $+>       Right (Just (Left 'a')) `shouldHave` _Right._Just++Finally, `shouldHave` can happily be used as a replacement for a vanilla `shouldBe`.++>     it "replaces 'shouldBe'" $+>       Right (Just (Left 'a')) `shouldHave` _Right._Just._Left.only 'a'+>+>     it "checks a bigger part of the structure for equality" $+>       Right (Just (Left 'a')) `shouldHave` _Right._Just.only (Left 'a')+>+>     it "checks the whole structure for equality" $+>       Right (Just (Left 'a')) `shouldHave` only (Right (Just (Left 'a')))++`shouldNotHave` is the opposite of `shouldHave` as its name implies, it checks+whether a `Fold` does not have any targets in the structure.++>   describe "shouldNotHave" $+>     it "is the opposite of 'shouldHave'" $+>       Right (Just (Left 'a')) `shouldNotHave` _Left++Next group of expectations is those of them that actually care about the result+of looking into the structure.  It consists of `shouldView`, `shouldPreview`,+`shouldList`, and `shouldPerform`.  They derive names from `view`, `preview`, `toListOf`,+and `perform` `combinators from the lens package.++`shouldView` works similarly to `view`, no big surprises here. If a `Fold` is actually+a `Getter`, you just get its target:++>   describe "shouldView" $ do+>     it "gets a single target verbatim" $+>       (1, (((1, 7), 8), 2, (3, 4), 5, 7)) `shouldView` 7 `through` _2._1._1._2++(`through` is just a fancy name for `id`; it helps to avoid parentheses)++Otherwise, if `Fold` has multiple targets, they are combined using `Monoid` instance+for the target type (and it better have one):++>     it "combines multiple targets using Monoid instance" $+>       [("foo", 1), ("bar", 2), ("baz", 3)] `shouldView` "foobarbaz" `through` folded._1++`shouldList` is like `toListOf`, that is, it combines its targets into the list:++>   describe "shouldList" $+>     it "combines multiple targets into list" $+>       [("foo", 1), ("bar", 2), ("baz", 3)] `shouldList` [1, 2, 3] `through` folded._2++`shouldPreview` is like `preview` in that it only cares about the first target:++>   describe "shouldPreview" $+>     it "gets the first target" $+>       [1..10] `shouldPreview` 10 `through` reversed.folded++`shouldPerform` performs the action and looks into the first target of the result.++>   describe "shouldPerform" $+>     it "performs an action and gets the first target" $+>       readFile "README.lhs" `shouldPerform` 99 `through` to lines.folded.prefixed ">".to length++The last combinator, which does not really belong to any of the previous groups,+is `shouldThrow`. It uses composable selectors to determine which+exception was thrown:++>   describe "shouldThrow" $ do+>     it "looks into the 'error' call" $+>       error "foo" `shouldThrow` _ErrorCall.only "foo"+>+>     it "looks into the division by zero" $+>       evaluate (1 `div` 0) `shouldThrow` _DivideByZero++  [hspec]: http://hspec.github.io/+  [lens]: https://github.com/ekmett/lens/
− README.md
@@ -1,6 +0,0 @@-hspec-expectations-lens-======-[![Hackage](https://budueba.com/hackage/hspec-expectations-lens)](http://hackage.haskell.org/package/hspec-expectations-lens)-[![Build Status](https://secure.travis-ci.org/supki/hspec-expectations-lens.png?branch=master)](http://travis-ci.org/supki/hspec-expectations-lens)--Hspec expectations for the lens stuff
hspec-expectations-lens.cabal view
@@ -1,5 +1,5 @@ name:                hspec-expectations-lens-version:             0.2.0.0+version:             0.2.1.0 synopsis:            Hspec expectations for the lens stuff description:   Package adds hspec expectations (@\`shouldX\`@ things)@@ -13,7 +13,7 @@ build-type:          Simple extra-source-files:   CHANGELOG.md-  README.md+  README.lhs cabal-version:       >= 1.10  source-repository head@@ -22,7 +22,7 @@  source-repository this   type:     git-  tag:      0.2.0.0+  tag:      0.2.1.0   location: https://github.com/supki/hspec-expectations-lens  library
src/Test/Hspec/Expectations/Lens.hs view
@@ -7,10 +7,12 @@   , shouldPreview   , shouldList   , shouldThrow+  , shouldPerform   , through   ) where  import Control.Lens+import Control.Monad import Control.Exception (SomeException) import Control.Exception.Lens import Data.Monoid (Any(..), All(..), First(..), Endo(..))@@ -19,11 +21,17 @@ import Text.Printf (printf)  -infixl 1 `shouldHave`, `shouldNotHave`, `shouldView`, `shouldPreview`, `shouldList`, `shouldThrow`, `through`+infixl 1 `shouldHave`, `shouldNotHave`+infixl 1 `shouldView`, `shouldPreview`, `shouldList`+infixl 1 `shouldThrow`+infixl 1 `shouldPerform`+infixl 1 `through` --- | @x \`shouldHave\` l@ sets the expectation that 'Fold' @l@ has--- non-zero number of targets in @x@+-- | @s \`shouldHave\` l@ sets the expectation that 'Fold' @l@ has+-- non-zero number of targets in the structure @s@ --+-- > s `shouldBe` t ≡ s `shouldHave` only t+-- -- @ -- shouldHave :: 'Show' s => s -> 'Getter'     s a -> 'Expectation' -- shouldHave :: 'Show' s => s -> 'Fold'       s a -> 'Expectation'@@ -33,12 +41,12 @@ -- shouldHave :: 'Show' s => s -> 'Prism''     s a -> 'Expectation' -- @ shouldHave :: Show s => s -> Getting Any s a -> Expectation-x `shouldHave` f = assertBool msg (has f x)+s `shouldHave` l = assertBool msg (has l s)  where-  msg = printf "Supplied Fold has zero targets for %s" (show x)+  msg = printf "This Fold has zero targets for %s" (show s) --- | @x \`shouldNotHave\` l@ sets the expectation that 'Fold' @l@--- has zero targets in @x@+-- | @s \`shouldNotHave\` l@ sets the expectation that 'Fold' @l@+-- has exactly zero targets in the structue @s@ -- -- @ -- shouldNotHave :: 'Show' s => s -> 'Getter'     s a -> 'Expectation'@@ -49,12 +57,12 @@ -- shouldNotHave :: 'Show' s => s -> 'Prism''     s a -> 'Expectation' -- @ shouldNotHave :: Show s => s -> Getting All s a -> Expectation-x `shouldNotHave` f = assertBool msg (hasn't f x)+s `shouldNotHave` l = assertBool msg (hasn't l s)  where-  msg = printf "Supplied Fold has non-zero targets for %s" (show x)+  msg = printf "This Fold has non-zero targets for %s" (show s) --- | @x \`shouldView\` y \`through\` l@ sets the expectation that--- you can see @y@ in @x@ though a 'Getter' @l@+-- | @s \`shouldView\` t \`through\` l@ sets the expectation that+-- you can see target @t@ in the structure @s@ though a 'Getter' @l@ -- -- @ -- shouldView ::           ('Show' s, 'Show' a, 'Eq' a) => s -> a -> 'Getter'     s a -> 'Expectation'@@ -65,12 +73,13 @@ -- shouldView :: ('Data.Monoid.Monoid' m, 'Show' s, 'Show' a, 'Eq' a) => s -> a -> 'Prism''     s m -> 'Expectation' -- @ shouldView :: (Show s, Show a, Eq a) => s -> a -> Getting a s a -> Expectation-(x `shouldView` y) l = assertBool msg (view l x == y)- where-  msg = printf "Can't view %s from %s through supplied Getter" (show y) (show x)+(s `shouldView` t) l =+  let r = view l s in+    unless (r == t) $+      assertFailure (printf "Resulted in %s, but expected %s" (show r) (show t)) --- | @x \`shouldPreview\` y \`through\` l@ sets the expectation that--- you can list @y@ in @x@ first though a 'Fold' @l@+-- | @s \`shouldPreview\` t \`through\` l@ sets the expectation that+-- you @y@ is the first target of the 'Fold' @l@ in @s@ -- -- @ -- shouldPreview :: ('Show' s, 'Show' a, 'Eq' a) => s -> a -> 'Getter'     s a -> 'Expectation'@@ -81,12 +90,15 @@ -- shouldPreview :: ('Show' s, 'Show' a, 'Eq' a) => s -> a -> 'Prism''     s a -> 'Expectation' -- @ shouldPreview :: (Show s, Show a, Eq a) => s -> a -> Getting (First a) s a -> Expectation-(x `shouldPreview` y) l = assertBool msg (preview l x == Just y)- where-  msg = printf "Can't preview %s from %s through supplied Fold" (show y) (show x)+(s `shouldPreview` t) l =+  case preview l s of+    Nothing ->+      assertFailure (printf "No targets, but expected %s" (show t))+    Just r  -> unless (r == t) $+      assertFailure (printf "Resulted in %s, but expected %s" (show r) (show t)) --- | @x \`shouldList\` ys \`through\` l@ sets the expectation that--- you can list @ys@ in @x@ though a 'Fold' @l@+-- | @s \`shouldList\` ts \`through\` l@ sets the expectation that+-- @ts@ is a list of the Fold @l@ targets in @x@ -- -- @ -- shouldList :: ('Show' s, 'Show' a, 'Eq' a) => s -> [a] -> 'Getter'     s a -> 'Expectation'@@ -97,29 +109,47 @@ -- shouldList :: ('Show' s, 'Show' a, 'Eq' a) => s -> [a] -> 'Prism''     s a -> 'Expectation' -- @ shouldList :: (Show s, Show a, Eq a) => s -> [a] -> Getting (Endo [a]) s a -> Expectation-(x `shouldList` y) l = assertBool msg (toListOf l x == y)- where-  msg = printf "Can't list %s from %s through supplied Fold" (show y) (show x)+(s `shouldList` t) l =+  let r = toListOf l s in+    unless (r == t) $+      assertFailure (printf "Resulted in %s, but expected %s" (show r) (show t)) --- | @x \`shouldthrow\` l@ sets the expectation that--- @x@ throws an exception catchable with a 'Fold' @l@+-- | @a \`shouldThrow\` l@ sets the expectation that+-- @a@ throws an exception that 'Fold' @l@ can catch ----- /Note:/ name conflicts with 'Test.Hspec.Expectations.shouldThrow'+-- "Test.Hspec" exports 'Test.Hspec.Expectations.shouldThrow' too; it+-- only allows @e -> Bool@ selectors, which is less general and often less convenient -- -- @--- shouldThrow :: 'IO' a -> -> 'Getter'     s b -> 'Expectation'--- shouldThrow :: 'IO' a -> -> 'Fold'       s b -> 'Expectation'--- shouldThrow :: 'IO' a -> -> 'Lens''      s b -> 'Expectation'--- shouldThrow :: 'IO' a -> -> 'Iso''       s b -> 'Expectation'--- shouldThrow :: 'IO' a -> -> 'Traversal'' s b -> 'Expectation'--- shouldThrow :: 'IO' a -> -> 'Prism''     s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Getter'     s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Fold'       s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Lens''      s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Iso''       s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Traversal'' s b -> 'Expectation'+-- shouldThrow :: 'IO' a -> 'Prism''     s b -> 'Expectation' -- @ shouldThrow :: IO a -> Getting (First b) SomeException b -> Expectation x `shouldThrow` l = do   r <- trying l x   case r of     Left  _ -> return ()-    Right _ -> assertFailure "Couldn't catch any exceptions with the supplied Fold"+    Right _ -> assertFailure "Couldn't catch any exceptions"++-- | @a \`shouldPerform\` t \`through\` l@ sets the expectation that @t@ is+-- a target of the 'MonadicFold' @l@ applied to the result of action @a@+--+-- @+-- shouldPerform :: ('Show' a, 'Eq' a) => 'IO' s -> a -> 'Action'      'IO' s a -> 'Expectation'+-- shouldPerform :: ('Show' a, 'Eq' a) => 'IO' s -> a -> 'MonadicFold' 'IO' s a -> 'Expectation'+-- @+shouldPerform :: (Show a, Eq a) => IO s -> a -> Acting IO (Leftmost a) s s a b -> Expectation+(x `shouldPerform` t) l = do+  r <- x ^!? acts.l+  case r of+    Nothing ->+      assertFailure (printf "No targets, but expected %s" (show t))+    Just r' -> unless (r' == t) $+      assertFailure (printf "Resulted in %s, but expected %s" (show r') (show t))  -- | A helper to fight parentheses --