tasty-laws (empty) → 0.2
raw patch · 11 files changed
+368/−0 lines, 11 filesdep +basedep +smallcheckdep +smallcheck-lawssetup-changed
Dependencies added: base, smallcheck, smallcheck-laws, smallcheck-series, tagged, tasty, tasty-laws, tasty-smallcheck, transformers
Files
- CHANGELOG.md +16/−0
- LICENSE +30/−0
- README.md +22/−0
- Setup.hs +2/−0
- Test/Tasty/Laws/Applicative.hs +49/−0
- Test/Tasty/Laws/Functor.hs +29/−0
- Test/Tasty/Laws/Monad.hs +36/−0
- Test/Tasty/Laws/Monoid.hs +26/−0
- stack.yaml +7/−0
- tasty-laws.cabal +52/−0
- tests/tasty.hs +99/−0
+ CHANGELOG.md view
@@ -0,0 +1,16 @@+# 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.2] - 2015-09-04+### Removed+- `smallcheck` specific modules from+ [`smallcheck-laws-0.1`](https://hackage.haskell.org/package/smallcheck-laws-0.1).+ This package now contains `Tasty` specific modules.++### Changed+- Simplify module hierarchy: `Test.Tasty.SmallCheck.Laws` -> `Test.Tasty.Laws`++[0.2]: https://github.com/jdnavarro/tasty-laws/compare/bf1caa5...v0.2
+ 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,22 @@+# Tasty Laws++[](https://hackage.haskell.org/package/tasty-laws)+[](https://travis-ci.org/jdnavarro/tasty-laws)++Preassembled `tasty` runners for property testing the following laws:++- Monoids+- Functors+- Applicatives+- Monads++It uses [`smallcheck-laws`](https://github.com/jdnavarro/smallcheck-laws) under+the hood. If you don't find any runners that suite you, you can use this+package as a reference to implement your own `smallcheck-laws` test runners.++## 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/Laws/Applicative.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.Tasty.Laws.Applicative where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (Applicative)+#endif+import Data.Functor.Identity (Identity)+import Data.Proxy (Proxy(..))+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)+import Test.SmallCheck.Series (Series, Serial(series))++import qualified Test.SmallCheck.Laws.Applicative as Applicative+import Test.Tasty.Laws.Functor++-- | @tasty@ 'TestTree' for 'Applicative' laws. You need to provide the type+-- wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.+testApplicative+ :: forall f a .+ ( Applicative f+ , Show a, Eq a+ , Show (f a), Eq (f a), (Eq (f (f a)))+ , Show (f (a -> a))+ , Serial IO a+ , Serial IO (f a)+ , Serial IO (a -> a)+ , Serial IO (f (a -> a))+ , Serial Identity a, Serial Identity (f a)+ )+ => Proxy (f a) -> TestTree+testApplicative proxy = testGroup "Applicative"+ [ testFunctor proxy+ , testProperty "pure id <*> v ≡ v"+ $ Applicative.identity (series :: Series IO (f a))+ , testProperty "(.) <$> u <*> v <*> w ≡ u <*> (v <*> w)"+ $ Applicative.composition+ (series :: Series IO (f (a -> a)))+ (series :: Series IO (f a))+ (series :: Series IO (f (a -> a)))+ , testProperty "pure f <*> pure x ≡ pure (f x)" $ Applicative.homomorphism+ (Proxy :: Proxy f)+ (series :: Series IO a)+ (series :: Series IO (a -> a))+ , testProperty "u <*> pure y ≡ pure ($ y) <*> u" $ Applicative.interchange+ (series :: Series IO a)+ (series :: Series IO (f (a -> a)))+ ]
+ Test/Tasty/Laws/Functor.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.Tasty.Laws.Functor where++import Data.Proxy (Proxy)+import Data.Functor.Identity (Identity)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)+import Test.SmallCheck.Series (Serial(series), Series)++import qualified Test.SmallCheck.Laws.Functor as Functor++-- | @tasty@ 'TestTree' for 'Functor' laws. You need to provide the type+-- wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.+testFunctor+ :: forall f a .+ ( Eq (f a), Eq (f (f a)), Functor f, Show a, Show (f a)+ , Serial IO (f a)+ , Serial IO (a -> a)+ , Serial Identity a, Serial Identity (f a)+ )+ => Proxy (f a) -> TestTree+testFunctor _ = testGroup "Functor laws"+ [ testProperty "fmap id ≡ id" $ Functor.identity (series :: Series IO (f a))+ , testProperty "fmap (f . g) ≡ fmap f . fmap g" $ Functor.composition+ (series :: Series IO (f a))+ (series :: Series IO (a -> a))+ (series :: Series IO (a -> a))+ ]
+ Test/Tasty/Laws/Monad.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.Tasty.Laws.Monad where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (Applicative)+#endif+import Data.Functor.Identity (Identity)+import Data.Proxy (Proxy(..))+import Test.SmallCheck.Series (Series, Serial(series))+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)+import qualified Test.SmallCheck.Laws.Monad as Monad++import Test.Tasty.Laws.Applicative++-- | @tasty@ 'TestTree' for 'Monad' laws. You need to provide the type+-- wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.+testMonad+ :: forall f a .+ ( Applicative f, Monad f+ , Show a, Show (f a), Show (f (a -> a))+ , Eq a, Eq (f a), Eq (f (f a))+ , Serial IO a, Serial IO (a -> a)+ , Serial IO (f a) ,Serial IO (f (a -> a)), Serial IO (a -> f a)+ , Serial Identity a, Serial Identity (f a)+ )+ => Proxy (f a) -> TestTree+testMonad proxy = testGroup "Monad laws"+ [ testApplicative proxy+ , testProperty "(m >>= f) >>= g ≡ m (f >=> g)"+ $ Monad.associativity (series :: Series IO (f a))+ (series :: Series IO (a -> f a))+ (series :: Series IO (a -> f a))+ ]
+ Test/Tasty/Laws/Monoid.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.Tasty.Laws.Monoid where++#if !MIN_VERSION_base(4,8,0)+import Data.Monoid (Monoid)+#endif+import Data.Proxy (Proxy)+import Test.SmallCheck.Series (Series, Serial(series))+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.SmallCheck (testProperty)++import qualified Test.SmallCheck.Laws.Monoid as Monoid++-- | @tasty@ 'TestTree' for 'Applicative' laws. You need to provide the type+-- wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.+testMonoid :: forall a . (Show a, Eq a, Monoid a, Serial IO a) => Proxy a -> TestTree+testMonoid _ = testGroup "Monoid laws"+ [ testProperty "mempty <> x ≡ x" $ Monoid.leftIdentity (series :: Series IO a)+ , testProperty "x <> mempty ≡ x" $ Monoid.rightIdentity (series :: Series IO a)+ , testProperty "x <> (y <> z) ≡ (x <> y) <> z"+ $ Monoid.associativity (series :: Series IO a) series series+ , testProperty "mconcat ≡ foldr mappend mempty"+ $ Monoid.mconcat (series :: Series IO a)+ ]
+ stack.yaml view
@@ -0,0 +1,7 @@+flags: {}+packages:+- '.'+extra-deps:+- smallcheck-laws-0.2+- smallcheck-series-0.5.1+resolver: lts-3.4
+ tasty-laws.cabal view
@@ -0,0 +1,52 @@+name: tasty-laws+version: 0.2+synopsis: Test common laws+description:+ Preassembled 'tasty' runners for property testing 'Monoid', 'Functor',+ 'Applicative' and 'Monad' laws.+license: BSD3+license-file: LICENSE+author: Danny Navarro+maintainer: j@dannynavarro.net+category: Testing+build-type: Simple+cabal-version: >=1.10+extra-source-files: README.md CHANGELOG.md stack.yaml++source-repository head+ type: git+ location: git://github.com/jdnavarro/tasty-laws.git++library+ ghc-options: -Wall+ default-language: Haskell2010+ exposed-modules: Test.Tasty.Laws.Applicative,+ Test.Tasty.Laws.Functor,+ Test.Tasty.Laws.Monad,+ Test.Tasty.Laws.Monoid+ build-depends: base >=4.6 && <4.9,+ smallcheck >=1.1.1,+ smallcheck-laws >=0.1,+ smallcheck-series >=0.3,+ tasty >=0.10,+ tasty-smallcheck >=0.8.0.1+ if impl(ghc < 7.10)+ build-depends: transformers >=0.3.0.0++ 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,+ smallcheck >=1.1.1,+ tasty >=0.10,+ smallcheck-laws >=0.1,+ tasty-laws++ if impl(ghc < 7.8)+ build-depends: tagged >=0.7.2
+ tests/tasty.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Main where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative ((<$>))+#endif+import Data.Monoid (Sum(..), Product(..))+import Data.Proxy (Proxy(..))++import Test.SmallCheck.Series (Serial(series))+import Test.Tasty (TestTree, defaultMain, testGroup)++import Test.Tasty.Laws.Applicative+import Test.Tasty.Laws.Functor+import Test.Tasty.Laws.Monad+import Test.Tasty.Laws.Monoid++main :: IO ()+main = defaultMain $ testGroup "Laws"+ [ monoidTests+ , functorTests+ , applicativeTests+ , monadTests+ ]++monoidTests :: TestTree+monoidTests = testGroup "Monoid"+ [ testGroup "Sum"+ [ testGroup "Int"+ [ testMonoid (Proxy :: Proxy (Sum Int)) ]+ , testGroup "Integer"+ [ testMonoid (Proxy :: Proxy (Sum Integer)) ]+ , testGroup "Float"+ [ testMonoid (Proxy :: Proxy (Sum Float)) ]+ ]+ , testGroup "Product"+ [ testGroup "Int"+ [ testMonoid (Proxy :: Proxy (Product Int)) ]+ , testGroup "Integer"+ [ testMonoid (Proxy :: Proxy (Product Integer)) ]+ , testGroup "Float"+ [ testMonoid (Proxy :: Proxy (Product Float)) ]+ ]+ ]++functorTests :: TestTree+functorTests = testGroup "Functor"+ [ testGroup "Maybe"+ [ testGroup "Int"+ [ testFunctor (Proxy :: Proxy (Maybe Int)) ]+ , testGroup "Char"+ [ testFunctor (Proxy :: Proxy (Maybe Char)) ]+ ]+ , testGroup "[]"+ [ testGroup "Bool"+ [ testFunctor (Proxy :: Proxy [Bool]) ]+ , testGroup "Int"+ [ testFunctor (Proxy :: Proxy [Int]) ]+ ]+ ]++applicativeTests :: TestTree+applicativeTests = testGroup "Applicative"+ [ testGroup "Maybe"+ [ testGroup "Int"+ [ testApplicative (Proxy :: Proxy (Maybe Int)) ]+ , testGroup "Float"+ [ testApplicative (Proxy :: Proxy (Maybe Float)) ]+ ]+ , testGroup "[]"+ [ testGroup "Bool"+ [ testApplicative (Proxy :: Proxy [Bool]) ]+ , testGroup "Char"+ [ testApplicative (Proxy :: Proxy [Char]) ]+ ]+ ]++monadTests :: TestTree+monadTests = testGroup "Monad"+ [ testGroup "Maybe"+ [ testGroup "()"+ [ testMonad (Proxy :: Proxy (Maybe ())) ]+ , testGroup "Int"+ [ testMonad (Proxy :: Proxy (Maybe Int)) ]+ ]+ , testGroup "[]"+ [ testGroup "()"+ [ testMonad (Proxy :: Proxy [()]) ]+ ]+ ]++instance (Monad m, Serial m a) => Serial m (Sum a) where+ series = Sum <$> series++instance (Monad m, Serial m a) => Serial m (Product a) where+ series = Product <$> series