packages feed

bdd (empty) → 0.1.0.0

raw patch · 8 files changed

+232/−0 lines, 8 filesdep +HUnitdep +basedep +directorysetup-changed

Dependencies added: HUnit, base, directory, mtl, process, test-framework, test-framework-hunit, transformers

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2014 Irek Jozwiak++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bdd.cabal view
@@ -0,0 +1,38 @@+Name:                bdd+Version:             0.1.0.0+Synopsis:            Behavior-Driven Development DSL+Homepage:            http://github.com/humane-software/haskell-bdd+License:             MIT+License-File:        LICENSE+Author:              Irek Jozwiak, Pavlo Kerestey+Maintainer:          irek@humane.software+Category:            Testing+Stability:           experimental+Build-Type:          Simple+Cabal-Version:       >=1.10+Description:         A domain-specific language for testing programs using Behavior-Driven Development (BDD) process.++extra-source-files:+  changelog.md++Library+  exposed-modules:     Test.Bdd, Test.Bdd.Internal+  hs-source-dirs:      src+  default-language:    Haskell2010+  build-depends:       base ==4.*+                      ,HUnit+                      ,mtl+                      ,transformers+  +Test-Suite system-tests+  type:       exitcode-stdio-1.0+  other-modules:       BddTest+  main-is:    SystemTests.hs+  hs-source-dirs: tests/system, src+  build-depends: base+                ,directory+                ,HUnit+                ,mtl+                ,process+                ,test-framework+                ,test-framework-hunit
+ changelog.md view
@@ -0,0 +1,3 @@+0.1.0.0++* Initial version
+ src/Test/Bdd.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE BangPatterns, ExistentialQuantification, FlexibleContexts, ImpredicativeTypes, Rank2Types, ScopedTypeVariables #-}+module Test.Bdd (+  (^?=)+ ,Given+ ,Then+ ,When+ ,andAfter_+ ,expectError_+ ,given_+ ,noError+ ,testThat+ ,then_+ ,when_+ ) where++import Control.Monad.Error.Class+import Test.Bdd.Internal+import Test.HUnit ((@?=))++type Given m a = Monad m => m a++type When m a = Monad m => m a++type Then m a = Monad m => a -> m ()++testThat :: GivenWithTeardown m+testThat = []++infixl 1 `given_`, `when_`, `then_`+infixl 2 `andAfter_`++given_ :: (StorableAsGivenWithTeardown m g,Monad m) => GivenWithTeardown m -> g -> GivenWithTeardown m+given_ gs g = gs ++ mkGiven g++andAfter_ :: m a -> (a -> m ()) -> (m a, a -> m ())+andAfter_ = (,)++when_ :: Monad m => GivenWithTeardown m -> When m b -> m b+when_ (GivenStore (g,t):gs) w = do+  v <- g+  res <- when_ gs w+  t v+  return res+when_ [] w = w++then_ :: When m a -> Then m a -> When m a+then_ !w t = w >>= (\res-> (t $! res) >> return res)++expectError_ :: MonadError e m => When m a -> Then m e -> When m ()+expectError_ w t = (w >> fail "expected exception was not thrown") `catchError` (\e->t e)++noError :: Then m a+noError = const (return ())++(^?=) :: (Eq a, Show a) => IO a -> a -> b -> IO ()+actualF ^?= expected = (\_->actualF >>= (@?= expected))
+ src/Test/Bdd/Internal.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE ExistentialQuantification, FlexibleInstances, MultiParamTypeClasses, Rank2Types #-}++module Test.Bdd.Internal (+  GivenStore(..)+ ,GivenWithTeardown+ ,StorableAsGivenWithTeardown(..)+ ) where++data GivenStore m = forall a. GivenStore (m a, a -> m ())++type GivenWithTeardown m = Monad m => [GivenStore m]++class StorableAsGivenWithTeardown m g where+  mkGiven :: g -> GivenWithTeardown m++instance StorableAsGivenWithTeardown m (m a) where+  mkGiven g = [GivenStore (g,const (return ()))]++instance StorableAsGivenWithTeardown m (m a, a -> m ()) where+  mkGiven = return . GivenStore
+ tests/system/BddTest.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE FlexibleContexts,RankNTypes,ScopedTypeVariables #-}++module BddTest (tests) where++import Control.Applicative ((<$>))+import Control.Arrow ((>>>))+import Control.Monad (when)+import Control.Exception+import Control.Monad.Writer+import System.Directory+import System.Process (runCommand)+import Test.Bdd+import Test.Bdd.Internal+import Test.HUnit++tests = test [++  "the most rudimentary construct (doesn't test anything yet)" ~:+    let runSomeImaginaryIOAction :: IO ()+        runSomeImaginaryIOAction = return ()+    in TestCase $+      testThat+      `when_` runSomeImaginaryIOAction++ ,"assert something" ~: do+    testThat+      `when_` writeFile "/tmp/BddTestFile" "xxx"+      `then_` readFile "/tmp/BddTestFile" ^?= "xxx"+    -- we'll explain how to teardown later+    void (runCommand "rm -f /tmp/BddTestFile")++ ,"multiple thens are possible" ~: do+    testThat+      `when_` writeFile "/tmp/BddTestFile" "xxx"+      `then_` readFile "/tmp/BddTestFile" ^?= "xxx"+      `then_` (elem "BddTestFile" <$> getDirectoryContents "/tmp/") ^?= True+    -- we'll explain how to teardown later+    void (runCommand "rm -f /tmp/BddTestFile")++ ,"preconditions are possible as givens" ~:+    let noFile :: FilePath -> Given IO ()+        noFile f = doesFileExist f >>= \b-> when b (removeFile f)+    in do+      testThat+        `given_` noFile "/tmp/BddTestFile"+        `when_` writeFile "/tmp/BddTestFile" "xxx"+        `then_` readFile "/tmp/BddTestFile" ^?= "xxx"+      -- we'll explain how to teardown later+      void (runCommand "rm -f /tmp/BddTestFile")++ -- TODO: to be implemented+ -- ,"given can have a teardown, it takes given's return value" ~:+ --    let directory :: FilePath -> Given IO FilePath+ --        directory f = removeDir f >> createDirectory f >> return f+ --        removeDir :: FilePath -> IO ()+ --        removeDir f = doesDirectoryExist f >>= \exists->+ --                      when exists (removeDirectoryRecursive f)+ --    in testThat+ --      `given_` directory "/tmp/BddTestDir" `andAfter_` removeDir+ --      `when_` writeFile "/tmp/BddTestDir/test" "xxx"+ --      `then_` readFile "/tmp/BddTestDir/test" ^?= "xxx"++ -- ,"order of execution" ~:+ --    execWriter (+ --      (testThat::GivenWithTeardown (Writer [String]))+ --      `given_` (tell ["given"]::Writer [String] ()) `andAfter_` const (tell ["teardown"])+ --      `when_` tell ["when"]+ --      `then_` const (tell ["then"])+ --     ) @?= ["given","when","then","teardown"]++ ,"can expect an error" ~:+    testThat+    `when_` readFile "/that_surely_not_exists"+    `expectError_` (show >>> (@?= "/that_surely_not_exists: openFile: does not exist (No such file or directory)"))++ ,"test will fail if expected exception not thrown" ~:+    (do+       testThat+         `when_` readFile "/etc/passwd"+         `expectError_` (show >>> (@?= "this will never be thrown"))+       fail "should fail but didn't"+     ) `catch` (\(e::SomeException)->assertBool "expectError did not fail" (show e /= "user error (should fail but didn't)"))+ ]
+ tests/system/SystemTests.hs view
@@ -0,0 +1,10 @@+module Main where++import qualified BddTest+import Control.Monad (void)+import Test.Framework+import Test.Framework.Providers.HUnit+import Test.HUnit++main :: IO ()+main = defaultMain (hUnitTestToTests BddTest.tests)