tasty-lens (empty) → 0.3
raw patch · 12 files changed
+726/−0 lines, 12 filesdep +basedep +lensdep +smallchecksetup-changed
Dependencies added: base, lens, smallcheck, smallcheck-lens, tagged, tasty, tasty-lens, tasty-smallcheck
Files
- CHANGELOG.md +27/−0
- LICENSE +30/−0
- README.md +35/−0
- Setup.hs +2/−0
- Test/Tasty/Lens/Iso.hs +93/−0
- Test/Tasty/Lens/Lens.hs +103/−0
- Test/Tasty/Lens/Prism.hs +92/−0
- Test/Tasty/Lens/Setter.hs +101/−0
- Test/Tasty/Lens/Traversal.hs +120/−0
- stack.yaml +7/−0
- tasty-lens.cabal +48/−0
- tests/tasty.hs +68/−0
+ CHANGELOG.md view
@@ -0,0 +1,27 @@+# Change Log+All notable changes to this project will be documented in this file. This file+follows the formatting recommendations from [Keep a+CHANGELOG](http://keepachangelog.com/). This project adheres to [Semantic+Versioning](http://semver.org/).++## [0.3] - 2015-09-11+### Added+- Multiple `TestTree`s with different settings for dealing with `SmallCheck`+ `Depth`.++### Removed+- `smallcheck` specific modules from+ [`smallcheck-lens-0.1`](https://hackage.haskell.org/package/smallcheck-lens-0.1).+ This package now contains `Tasty` specific modules.++### Changed+- Simplify module hierarchy: `Test.Tasty.SmallCheck.Lens` -> `Test.Tasty.Lens`++## [0.1] - 2015-05-27+### Added+- `SmallCheck` properties for each lens laws.+- `tasty` test trees for each `Lens` type.+- Tests for some `Lens`.++[0.3]: https://github.com/jdnavarro/tasty-lens/compare/v0.1...v0.3+[0.1]: https://github.com/jdnavarro/tasty-lens/compare/1df060...v0.1
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, J Daniel Navarro++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of J. Daniel Navarro nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,35 @@+# Tasty Lens++[](https://hackage.haskell.org/package/tasty-lens)+[](https://travis-ci.org/jdnavarro/tasty-lens)++Preassembled [`tasty`](https://hackage.haskell.org/package/tasty) `TestTree`s+with sensible defaults for the validation of:++- `Lens`+- `Setter`+- `Traversal`+- `Iso`+- `Prism`++Although these tests offer weaker guarantees compared to manually proving the+laws through equational reasoning, they can still be useful for regression+testing where you don't want to manually proof every time you make a slight+change that could affect the laws.++It uses [`smallcheck-lens`](https://github.com/jdnavarro/smallcheck-laws)+under the hood. If you don't find any functions to create the `TestTree`s you+are looking for, you may want to use the `smallcheck-lens` package directly.+In such case you can still check this package as a reference to implement your+own `smallcheck-lens` `TestTree`s.++Check the+[tests](https://github.com/jdnavarro/tasty-lens/blob/master/tests/tasty.hs) in+this package for usage examples.++## Contact++Contributions and bug reports are welcome!++Please feel free to contact jdnavarro on the #haskell IRC channel on+irc.freenode.net.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Test/Tasty/Lens/Iso.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- | This module is intended to be imported @qualified@, for example:+--+-- > import qualified Test.Tasty.Lens.Iso as Iso+--+module Test.Tasty.Lens.Iso+ (+ -- * Tests+ test+ , testSeries+ , testExhaustive+ -- * Re-exports+ , module Test.SmallCheck.Lens.Iso+ ) where++import Control.Lens+import Test.SmallCheck.Series (Serial(series), CoSerial, Series)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import Test.SmallCheck.Lens.Iso (hither, yon)+import qualified Test.Tasty.Lens.Lens as Lens++-- | An 'Iso'' is only legal if the following laws hold:+--+-- 1. @s ^. l . from l ≡ s@+--+-- 2. @s ^. from l . l ≡ s@+--+-- It uses the 'Serial' and 'CoSerial' instances for @s@ and @a@. If you are+-- not creating your own orphan instances be aware of combinatorial explosion+-- since the default implementations usually aim for exhaustivity.+--+-- This uses "Test.Tasty.Lens.Lens"@.@'Lens.test' to validate the 'Iso'' is+-- a valid 'Lens'' in both normal and reverse form.+test+ :: ( Eq s, Eq a, Show s, Show a+ , Serial Identity s, Serial IO s, CoSerial IO s+ , Serial Identity a, Serial IO a, CoSerial IO a+ )+ => Iso' s a -> TestTree+test l = testSeries l series series++-- | An 'Iso'' is only legal if the following laws hold:+--+-- 1. @s ^. l . from l ≡ s@+--+-- 2. @s ^. from l . l ≡ s@+--+-- As in 'test' both @s@ and @a@ need to be 'Serial' and 'CoSerial' instances,+-- but here you explicitly pass custom 'Series' of @s@ and @a@ for the forward+-- case, while the reverse case still uses 'Serial' and 'CoSerial' instances.+-- If you want to fine tune both the forward and reverse cases, you should+-- create your own 'TestTree'.+--+-- This uses "Test.Tasty.Lens.Lens"@.@'Lens.testSeries', with the custom+-- 'Series' for @s@ and @a@, to validate the 'Iso'' is a valid 'Lens'' in both+-- normal and reverse form.+testSeries+ :: ( Eq s, Eq a, Show s, Show a+ , Serial Identity s, Serial IO s, CoSerial IO s+ , Serial Identity a, Serial IO a, CoSerial IO a+ )+ => Iso' s a -> Series IO s -> Series IO a -> TestTree+testSeries l ss as = testGroup "Iso Laws"+ [ testProperty "s ^. l . from l ≡ s" $ hither l ss+ , testProperty "s ^. from l . l ≡ s" $ yon l as+ , Lens.testSeries l ss+ , Lens.testSeries (from l) as+ ]++-- | An 'Iso'' is only legal if the following laws hold:+--+-- 1. @s ^. l . from l ≡ s@+--+-- 2. @s ^. from l . l ≡ s@+--+-- This is the same as 'test' except it uses+-- "Test.Tasty.Lens.Lens"@.@'Lens.testExhaustive' to validate the 'Lens'' laws.+-- Be aware of combinatorial explosions.+testExhaustive+ :: ( Eq s, Eq a, Show s, Show a+ , Serial Identity s, Serial IO s, CoSerial IO s+ , Serial Identity a, Serial IO a, CoSerial IO a+ )+ => Iso' s a -> TestTree+testExhaustive l = testGroup "Iso Laws"+ [ testProperty "s ^. l . from l ≡ s" $ hither l series+ , testProperty "s ^. from l . l ≡ s" $ yon l series+ , Lens.testExhaustive l+ , Lens.testExhaustive (from l)+ ]
+ Test/Tasty/Lens/Lens.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- | This module is intended to be imported @qualified@, for example:+--+-- > import qualified Test.Tasty.Lens.Lens as Lens+--+module Test.Tasty.Lens.Lens+ (+ -- * Tests+ test+ , testSeries+ , testExhaustive+ -- * Re-exports+ , module Test.SmallCheck.Lens.Lens+ ) where++import Data.Proxy (Proxy(..))++import Control.Lens+import Test.SmallCheck.Series (Serial(series), CoSerial, Series)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import Test.SmallCheck.Lens.Lens (setView, viewSet)+import qualified Test.Tasty.Lens.Traversal as Traversal++-- | A 'Lens'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @view l (set l b a) ≡ b@+--+-- 2. @set l (view l a) a ≡ a@+--+-- 3. @set l c (set l b a) ≡ set l c a@+--+-- It uses the 'Serial' and 'CoSerial' instances for @s@ and @a@. If you are+-- not creating your own orphan instances be aware of combinatorial explosion+-- since the default implementations usually aim for exhaustivity.+--+-- This also uses "Test.Tasty.Lens.Traversal"@.@'Traversal.test', with the+-- 'Maybe' functor, to validate the 'Lens'' is a valid 'Traversal''.+test+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Lens' s a -> TestTree+test l = testSeries l series++-- | A 'Lens'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @view l (set l b a) ≡ b@+--+-- 2. @set l (view l a) a ≡ a@+--+-- 3. @set l c (set l b a) ≡ set l c a@+--+-- Here you explicitly pass a custom 'Series' for @s@, while for @a@ the+-- @Serial@ instance is used. If you want to fine tune both 'Series', you+-- should create your own 'TestTree'.+--+-- This also uses "Test.Tasty.Lens.Traversal"@.@'Traversal.testSeries', with+-- the 'Maybe' functor and the custom @s@ 'Series', to validate the 'Lens'' is+-- a valid 'Traversal''.+testSeries+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Lens' s a -> Series IO s -> TestTree+testSeries l ss = testGroup "Lens Laws"+ [ testProperty "view l (set l b a) ≡ b" $+ setView l ss+ , testProperty "set l (view l a) a ≡ a" $+ viewSet l ss series+ , Traversal.testSeries (Proxy :: Proxy Maybe) l ss+ ]++-- | A 'Lens'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @view l (set l b a) ≡ b@+--+-- 2. @set l (view l a) a ≡ a@+--+-- 3. @set l c (set l b a) ≡ set l c a@+--+-- This is like the same as 'test' except it uses+-- "Test.Tasty.Lens.Traversal"@.@'Traversal.testExhaustive' to validate+-- 'Traversal'' laws. Be aware of combinatorial explosions.+testExhaustive+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Lens' s a -> TestTree+testExhaustive l = testGroup "Lens Laws"+ [ testProperty "view l (set l b a) ≡ b" $+ setView l series+ , testProperty "set l (view l a) a ≡ a" $+ viewSet l series series+ , Traversal.testExhaustive (Proxy :: Proxy Maybe) l+ ]
+ Test/Tasty/Lens/Prism.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- | This module is intended to be imported @qualified@, for example:+--+-- > import qualified Test.Tasty.Lens.Prism as Prism+--+module Test.Tasty.Lens.Prism+ (+ -- * Tests+ test+ , testExhaustive+ -- * Re-exports+ , module Test.SmallCheck.Lens.Prism+ ) where++import Data.Proxy (Proxy(..))++import Control.Lens+import Test.SmallCheck.Series (Serial(series), Series, CoSerial)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import Test.SmallCheck.Lens.Prism (yin, yang)+import qualified Test.Tasty.Lens.Traversal as Traversal++-- | A 'Prism'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @preview l (review l b) ≡ Just b"@+--+-- 2. @maybe s (review l) (preview l s) ≡ s@+--+-- It uses the 'Serial' and 'CoSerial' instances for @s@ and @a@. If you are+-- not creating your own orphan instances be aware of combinatorial explosion+-- since the default implementations usually aim for exhaustivity.+--+-- This also uses "Test.Tasty.Lens.Traversal"@.@'Traversal.test', with the+-- 'Maybe' functor, to validate the 'Prism'' is a valid 'Traversal''.+test+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Prism' s a -> TestTree+test l = testSeries l series++-- | A 'Prism'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @preview l (review l b) ≡ Just b"@+--+-- 2. @maybe s (review l) (preview l s) ≡ s@+--+-- Here you explicitly pass a custom 'Series' for @s@, while for @a@ the+-- @Serial@ instance is used. If you want to fine tune both 'Series', you+-- should create your own 'TestTree'.+--+-- This also uses "Test.Tasty.Lens.Traversal"@.@'Traversal.testSeries', with+-- the 'Maybe' functor and the custom @s@ 'Series', to validate the 'Prism'' is+-- a valid 'Traversal''.+testSeries+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Prism' s a -> Series IO s -> TestTree+testSeries l ss = testGroup "Prism Laws"+ [ testProperty "preview l (review l b) ≡ Just b" $ yin l series+ , testProperty "maybe s (review l) (preview l s) ≡ s" $ yang l ss+ , Traversal.testSeries (Proxy :: Proxy Maybe) l ss+ ]++-- | A 'Prism'' is only legal if it's a valid 'Traversal'' and if the following+-- laws hold:+--+-- 1. @preview l (review l b) ≡ Just b"@+--+-- 2. @maybe s (review l) (preview l s) ≡ s@+--+-- This is the same as 'test' except it uses+-- "Test.Tasty.Lens.Traversal"@.@'Traversal.testExhaustive' to validate+-- 'Traversal'' laws. Be aware of combinatorial explosions.+testExhaustive+ :: ( Eq s, Eq a, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, CoSerial IO a+ )+ => Prism' s a -> TestTree+testExhaustive l = testGroup "Prism Laws"+ [ testProperty "preview l (review l b) ≡ Just b" $ yin l series+ , testProperty "maybe s (review l) (preview l s) ≡ s" $ yang l series+ , Traversal.testExhaustive (Proxy :: Proxy Maybe) l+ ]
+ Test/Tasty/Lens/Setter.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- | This module is intended to be imported @qualified@, for example:+--+-- > import qualified Test.Tasty.Lens.Setter as Setter+--+module Test.Tasty.Lens.Setter+ (+ -- * Tests+ test+ , testSeries+ , testExhaustive+ -- * Re-exports+ , module Test.SmallCheck.Lens.Setter+ ) where++import Control.Lens+import Test.SmallCheck.Series (Serial(series), Series)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import Test.SmallCheck.Lens.Setter+ ( identity+ , setSet+ , setSetSum+ , composition+ , compositionSum+ )++-- | A 'Setter' is only legal if the following laws hold:+--+-- 1. @set l y (set l x a) ≡ set l y a@+--+-- 2. @over l id ≡ id@+--+-- 3. @over l f . over l g ≡ over l (f . g)@+--+-- The 'Serial' and 'CoSerial' instances for @s@ and @a@. If you are+-- not creating your own orphan instances be aware of combinatorial explosion+-- since the default implementations usually aim for exhaustivity.+--+-- In this case @f@ and @g@ are of type @a -> a@ and when combining them the+-- /sum/ of 'Series' is used.+test+ :: ( Eq s, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, Serial IO (a -> a)+ )+ => Setter' s a -> TestTree+test l = testSeries l series++-- | A 'Setter' is only legal if the following laws hold:+--+-- 1. @set l y (set l x a) ≡ set l y a@+--+-- 2. @over l id ≡ id@+--+-- 3. @over l f . over l g ≡ over l (f . g)@+--+-- Here you explicitly pass a custom 'Series' for @s@, while for @a@ the+-- @Serial@ instance is used. If you want to fine tune both 'Series', you+-- should create your own 'TestTree'.+--+-- In this case @f@ and @g@ are of type @a -> a@ and when combining them the+-- /sum/ of 'Series' is used.+testSeries+ :: ( Eq s, Show s, Show a+ , Serial IO a, Serial Identity a, Serial IO (a -> a)+ )+ => Setter' s a -> Series IO s -> TestTree+testSeries l ss = testGroup "Setter Laws"+ [ testProperty "over l id ≡ id" $ identity l ss+ , testProperty "set l y (set l x a) ≡ set l y a" $+ setSetSum l ss series series+ , testProperty "over l f . over l g ≡ over l (f . g)" $+ compositionSum l ss series series+ ]++-- | A 'Setter' is only legal if the following laws hold:+--+-- 1. @set l y (set l x a) ≡ set l y a@+--+-- 2. @over l id ≡ id@+--+-- 3. @over l f . over l g ≡ over l (f . g)@+--+-- This is the same as 'test' except it uses the /product/ when combining the+-- @f@ and @g@ 'Series'.+testExhaustive+ :: ( Eq s, Show s, Show a+ , Serial IO s+ , Serial IO a, Serial Identity a, Serial IO (a -> a)+ )+ => Setter' s a -> TestTree+testExhaustive l = testGroup "Setter Laws"+ [ testProperty "over l id ≡ id" $ identity l series+ , testProperty "set l y (set l x a) ≡ set l y a" $+ setSet l series series series+ , testProperty "over l f . over l g ≡ over l (f . g)" $+ composition l series series series+ ]
+ Test/Tasty/Lens/Traversal.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | This module is intended to be imported @qualified@, for example:+--+-- > import qualified Test.Tasty.Lens.Traversal as Traversal+--+module Test.Tasty.Lens.Traversal+ (+ -- * Tests+ test+ , testSeries+ , testExhaustive+ -- * Re-exports+ , module Test.SmallCheck.Lens.Traversal+ ) where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (Applicative)+#endif+import Data.Proxy (Proxy(..))++import Control.Lens+import Test.SmallCheck.Series (Serial(series), CoSerial, Series)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import qualified Test.SmallCheck.Lens.Traversal as Traversal+import Test.SmallCheck.Lens.Traversal (composition, compositionSum)+import qualified Test.Tasty.Lens.Setter as Setter++-- | A 'Traversal'' is only legal if it is a valid 'Setter'' and if the+-- following laws hold:+--+-- 1. @t pure ≡ pure@+--+-- 2. @fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)@+--+-- The 'Serial' and 'CoSerial' instances for @s@ and @a@. If you are+-- not creating your own orphan instances be aware of combinatorial explosion+-- since the default implementations usually aim for exhaustivity.+--+-- The 'Proxy' arguments lets you choose the 'Functor' to use in the tests. @f@+-- and @g@ are of type @a -> functor a@ and when combining them the /sum/ of+-- 'Series' is used.+--+-- This also uses "Test.Tasty.Lens.Setter"@.@'Setter.test' to validate the+-- 'Traversal'' is a valid 'Setter''.+test+ :: forall f s a .+ ( Applicative f + , Eq s, Eq (f s), Eq (f (f s))+ , Show s, Show a, Show (f a)+ , Serial IO s+ , Serial Identity a, Serial IO a, Serial IO (f a), CoSerial IO a+ )+ => Proxy f -> Traversal' s a -> TestTree+test p t = testSeries p t series++-- | A 'Traversal'' is only legal if it is a valid 'Setter'' and if the+-- following laws hold:+--+-- 1. @t pure ≡ pure@+--+-- 2. @fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)@+--+-- Here you explicitly pass a custom 'Series' for @s@, while for @a@ the+-- @Serial@ instance is used. If you want to fine tune both 'Series', you+-- should create your own 'TestTree'.+--+-- The 'Proxy' arguments lets you choose the 'Functor' to use in the tests. @f@+-- and @g@ are of type @a -> functor a@ and when combining them the /sum/ of+-- 'Series' is used.+--+-- This also uses "Test.Tasty.Lens.Setter"@.@'Setter.test' to validate the+-- 'Traversal'' is a valid 'Setter''.+testSeries+ :: forall f s a .+ ( Applicative f + , Eq s, Eq (f s), Eq (f (f s))+ , Show s, Show a, Show (f a)+ , Serial Identity a, Serial IO a, Serial IO (f a), CoSerial IO a+ )+ => Proxy f -> Traversal' s a -> Series IO s -> TestTree+testSeries p t ss = testGroup "Traversal Laws"+ [ testProperty "t pure ≡ pure" $ Traversal.pure p t ss+ , testProperty "fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)" $+ compositionSum t ss (series :: Series IO (a -> f a))+ (series :: Series IO (a -> f a))+ , Setter.testSeries t ss+ ]+++-- | A 'Traversal'' is only legal if it is a valid 'Setter'' and if the+-- following laws hold:+--+-- 1. @t pure ≡ pure@+--+-- 2. @fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)@+--+-- This is the same as 'test' except it uses the /product/ when combining the+-- @f@ and @g@ 'Series' and "Test.Tasty.Lens.Setter"@.@'Setter.testExhaustive'+-- to validate 'Setter'' laws. Be aware of combinatorial explosions.+testExhaustive+ :: forall f s a .+ ( Applicative f + , Eq s, Eq (f s), Eq (f (f s))+ , Show s, Show a, Show (f a)+ , Serial IO s+ , Serial Identity a, Serial IO a, Serial IO (f a), CoSerial IO a+ )+ => Proxy f -> Traversal' s a -> TestTree+testExhaustive p t = testGroup "Traversal Laws"+ [ testProperty "t pure ≡ pure" $ Traversal.pure p t series+ , testProperty "fmap (t f) . t g ≡ getCompose . t (Compose . fmap f . g)" $+ composition t series (series :: Series IO (a -> f a))+ (series :: Series IO (a -> f a))+ , Setter.testExhaustive t+ ]
+ stack.yaml view
@@ -0,0 +1,7 @@+flags: {}+packages:+- '.'+extra-deps:+- smallcheck-lens-0.3+- smallcheck-series-0.5.1+resolver: lts-3.4
+ tasty-lens.cabal view
@@ -0,0 +1,48 @@+name: tasty-lens+version: 0.3+synopsis: Tasty TestTrees for Lens validation+description:+ Preassembled 'tasty' 'TestTree's for property testing @Lens@es, @Setter@s,+ @Traversal@s, @Iso@s and @Prism@s laws.+homepage: https://github.com/jdnavarro/tasty-lens+bug-reports: https://github.com/jdnavarro/tasty-lens/issues+license: BSD3+license-file: LICENSE+author: Danny Navarro+maintainer: j@dannynavarro.net+category: Testing, Lenses+build-type: Simple+extra-source-files: README.md CHANGELOG.md stack.yaml+cabal-version: >=1.10++source-repository head+ type: git+ location: git://github.com/jdnavarro/tasty-lens.git++library+ default-language: Haskell2010+ ghc-options: -Wall+ exposed-modules: Test.Tasty.Lens.Iso+ Test.Tasty.Lens.Lens+ Test.Tasty.Lens.Prism+ Test.Tasty.Lens.Setter+ Test.Tasty.Lens.Traversal+ build-depends: base >=4.6 && <4.9,+ lens >=4.1.2.1,+ smallcheck >=1.1.1,+ smallcheck-lens >=0.3,+ tasty >=0.10,+ tasty-smallcheck >=0.8.0.1+ if impl(ghc < 7.8)+ build-depends: tagged >=0.7.2++test-suite tasty+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: tasty.hs+ ghc-options: -Wall -threaded+ build-depends: base >= 4.6 && <4.9,+ lens >=4.1.2.1,+ tasty >=0.10,+ tasty-lens
+ tests/tasty.hs view
@@ -0,0 +1,68 @@+module Main where++import Control.Lens+import Numeric.Lens (hex, negated, adding)+import Test.Tasty (TestTree, defaultMain, testGroup)++import qualified Test.Tasty.Lens.Iso as Iso+import qualified Test.Tasty.Lens.Lens as Lens+import qualified Test.Tasty.Lens.Prism as Prism++main :: IO ()+main = defaultMain $ testGroup "Lens tests"+ [ tupleTests+ , maybeTests+ , numTests+ ]++tupleTests :: TestTree+tupleTests = testGroup "Tuples"+ [ testGroup "_1"+ [ testGroup "Lens' (Char,Char) Char"+ [ Lens.test (_1 :: Lens' (Char,Char) Char) ]+ , testGroup "Lens' (Int,Char) Int"+ [ Lens.test (_1 :: Lens' (Int,Char) Int) ]+ ]+ , testGroup "_2"+ [ testGroup "Lens' (Char,Char,Char) Char"+ [ Lens.test (_2 :: Lens' (Char,Char,Char) Char) ]+ ]+ ]++maybeTests :: TestTree+maybeTests = testGroup "Maybe"+ [ testGroup "_Nothing"+ [ testGroup "Prism' (Maybe Char) ()"+ [ Prism.test (_Nothing :: Prism' (Maybe Char) ()) ]+ , testGroup "Prism' (Maybe Int) ()"+ [ Prism.test (_Nothing :: Prism' (Maybe Int) ()) ]+ ]+ , testGroup "_Just"+ [ testGroup "Prism' (Maybe Char) Char"+ [ Prism.test (_Just :: Prism' (Maybe Char) Char) ]+ , testGroup "Prism' (Maybe Int) Int"+ [ Prism.test (_Just :: Prism' (Maybe Int) Int) ]+ ]+ ]++numTests :: TestTree+numTests = testGroup "Numeric"+ [ testGroup "negated"+ [ testGroup "Iso' Int Int"+ [ Iso.test (negated :: Iso' Int Int) ]+ , testGroup "Iso' Float Float"+ [ Iso.test (negated :: Iso' Float Float) ]+ ]+ , testGroup "hex"+ [ testGroup "Prism'' String Int"+ [ Prism.test (hex :: Prism' String Int) ]+ , testGroup "Prism'' String Integer"+ [ Prism.test (hex :: Prism' String Integer) ]+ ]+ , testGroup "adding"+ [ testGroup "Iso' Int Int"+ [ Iso.test (adding 2 :: Iso' Int Int) ]+ , testGroup "Iso' Integer Integer"+ [ Iso.test (adding 3 :: Iso' Integer Integer) ]+ ]+ ]