tdd-util 0.1.0.1 → 0.2.0.1
raw patch · 3 files changed
+232/−14 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Test.Util: timelimitExceeded_callerName :: Lens TimeLimitExceeded TimeLimitExceeded String String
+ Test.Util: timelimitExceeded_callerName :: Lens' TimeLimitExceeded String
- Test.Util: timelimitExceeded_message :: Lens TimeLimitExceeded TimeLimitExceeded (Maybe String) (Maybe String)
+ Test.Util: timelimitExceeded_message :: Lens' TimeLimitExceeded (Maybe String)
- Test.Util: timelimitExceeded_microseconds :: Lens TimeLimitExceeded TimeLimitExceeded Integer Integer
+ Test.Util: timelimitExceeded_microseconds :: Lens' TimeLimitExceeded Integer
- Test.Util: timeoutOverflow_inputBound :: Lens TimeoutOverflow TimeoutOverflow Integer Integer
+ Test.Util: timeoutOverflow_inputBound :: Lens' TimeoutOverflow Integer
- Test.Util: timeoutOverflow_message :: Lens TimeoutOverflow TimeoutOverflow (Maybe String) (Maybe String)
+ Test.Util: timeoutOverflow_message :: Lens' TimeoutOverflow (Maybe String)
- Test.Util: timeoutOverflow_microseconds :: Lens TimeoutOverflow TimeoutOverflow Integer Integer
+ Test.Util: timeoutOverflow_microseconds :: Lens' TimeoutOverflow Integer
Files
- src/Test/Util.hs +4/−2
- tdd-util.cabal +222/−6
- testsrc/Test/Test/Util.hs +6/−6
src/Test/Util.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE GADTs, TemplateHaskell, DeriveDataTypeable #-} --- | A module for various useful functions for TDD missing in other libraries.+-- | A module containing utilities for testing with @test-framework@, @HUnit@,+-- and @testable@. module Test.Util ( -- * Throwing and catching exceptions@@ -8,7 +9,8 @@ , assertThrown , assertNotThrown - -- * Concurrent TDD (TODO: provide a means of testing a monadic property with many threads)+ -- * Concurrent TDD+ -- TODO: provide a means of testing a monadic property with many threads -- * Process timing , timeMicroseconds
tdd-util.cabal view
@@ -1,5 +1,5 @@ name: tdd-util-version: 0.1.0.1+version: 0.2.0.1 cabal-version: >= 1.10 build-type: Simple license: BSD3@@ -7,13 +7,229 @@ copyright: Copyright (c) 2012 Byron James Johnson author: Byron James Johnson maintainer: Byron James Johnson <ByronJohnsonFP@gmail.com>-synopsis: Utilities for TDD with test-framework, HUnit, and QuickCheck+synopsis: Test framework wrapper description:- This library provides utility functions for TDD in the manner of "MissingH".+ tdd-util is a small test framework for TDD (cf.+ <https://en.wikipedia.org/wiki/Test-driven_development>) that integrates+ three testing libraries, whose modules are all exported under+ "Test.Util.Framework", while providing utilities based on each of these,+ exported under "Test.Util", by wrapping the library @test-framework@. .- This package contains a test suite that is an excellent example of using- this library and may be cargo culted to save time starting TDD on a new- project.+ /Getting Started/+ .+ To get started, an example that uses this library is this library's test+ suite itself and can be found at+ <https://github.com/bairyn/tdd-util/tree/master/testsrc>. Each module under+ @src@ corresponds with a module under @testsrc\/Test@ that contains the tests+ for that module. (For example, this library currently exports two modules in+ @src\/Test\/Util.hs@ and @src\/Test\/Util\/Framework.hs@; their tests are located,+ respectively, in @testsrc\/Test\/Test\/Util.hs@ and+ @testsrc\/Test\/Test\/Util\/Framework.hs@; and a module in @src\/Data\/Trie.hs@+ would correspond with a test module in @testsrc\/Test\/Trie.hs@). This structure can be conveniently+ cargo culted from this library, but these conventions are not enforced.+ .+ /Test Modules/+ .+ Conventially, each module in @src\/X.hs@ corresponds with a module that contains+ tests for that module located at @testsrc\/Test\/X.hs@. None of these Test+ modules depend on each other by importing them. For a concrete example of+ such a test module, see <https://github.com/bairyn/tdd-util/blob/master/testsrc/Test/Test/Util.hs>.+ .+ Each test module exports a list of @test-framework@\'s 'TTest's (an alias to+ disambiguate between @Test@ types from different libraries) named @tests@.+ .+ This list of tests can either be run individually by importing the test+ module, and then running @'defaultMain' tests@; or be grouped together in the+ test-suite's @Tests@ module (see below).+ .+ In the tests themselves, very briefly, @'testGroup' \"Brief description of+ test\" […]@ can be used to construct a single test-framework test ('TTest')+ from a group of other tests, @'testProperty' name prop_foo @ can be used to construct a+ 'TTest' from a QuickCheck property, and @'testCase' name $ do …@ can be used+ to construct a test from 'HUnit'. See test-framework's+ documentation for more information about constructing QuickCheck and HUnit+ properties.+ .+ Here is a segment of code from+ <https://github.com/bairyn/tdd-util/blob/master/testsrc/Test/Test/Util.hs>:+ .+ @+ module Test.Test.Util+ ( tests+ ) where+ .+ import Control.Applicative+ …+ import Text.Printf+ .+ import Test.Util+ import Test.Util.Framework+ …+ tests :: [TTest]+ tests =+ [ testGroup \"Throwing and catching exceptions - isExceptionThrown\" $+ [ testCase \"throwing an exception\" $ do+ thrown <- isExceptionThrown $ do+ throwIO $ AssertionFailed \"assertion failed\"+ when (either (\e -> flip const (e :: AssertionFailed) $ False) (const True) $ thrown) $ do+ assertString \"exception NOT thrown\"+ , testCase \"not throwing an exception\" $ do+ thrown <- isExceptionThrown $ do+ return ()+ when (either (\e -> flip const (e :: AssertionFailed) $ True) (const False) $ thrown) $ do+ assertString \"exception thrown\"+ ]+ , testGroup \"Throwing and catching exceptions - assert*Thrown\" $+ …+ ]+ …+ @+ .+ /Tests.hs/+ .+ Each test module is conventionally grouped into a single test module, at+ @testsrc\/Tests.hs@ (e.g. see+ <https://github.com/bairyn/tdd-util/blob/master/testsrc/Tests.hs>), that+ exports a list of 'TTest's named @tests@. Interactively, this test module+ can be loaded in ghci, and the tests can be run as before, with @defaultMain+ tests@.+ .+ These tests can also be specified in the project's cabal file, by invoking+ @defaultMain@ on @tests@ in an external @Main.hs@ file under @testsrc@ (e.g.+ see <https://github.com/bairyn/tdd-util/blob/master/testsrc/Main.hs>).+ Running this @Main.hs@ will result in the test suite being run, so a+ @test-suite@ section can be added to the cabal file as it is in+ <https://github.com/bairyn/tdd-util/blob/master/tdd-util.cabal>.+ .+ When a test suite is specified, cabal will recognized it and, when+ configured to do so, will run it when installing your package, resulting in+ output that may look like this when it succeeds.+ .+ @+ Running 1 test suites...+ Test suite tdd-util-tests: RUNNING...+ Test suite tdd-util-tests: PASS+ Test suite logged to: dist\/test\/tdd-util-0.1.0.1-tdd-util-tests.log+ 1 of 1 test suites (1 of 1 test cases) passed.+ @+ .+ This package's @Tests.hs@:+ .+ @+ module Tests+ ( tests+ ) where+ .+ import Test.Util.Framework+ .+ import qualified Test.Test.Util+ import qualified Test.Test.Util.Framework+ .+ tests :: [TTest]+ tests =+ [ testGroup \"Test.Test.Util.tests\" $ Test.Test.Util.tests+ , testGroup \"Test.Test.Util.Framework.tests\" $ Test.Test.Util.Framework.tests+ ]+ @+ .+ /Main.hs Example/+ .+ @Main.hs@ conventially defines a simple program that invokes @defaultMain+ tests@ from the test group that encapsulates the entire test suite in+ @Tests.hs@. Here is this package's @Main.hs@ file:+ .+ @+ module Main where+ .+ import Test.Util.Framework+ .+ import Tests+ .+ main :: IO ()+ main = do+ defaultMain tests+ @+ .+ /Cabal Configuration/+ .+ Your package's cabal configuration can be updated to point to+ @testsrc\/Main.hs\/@; here is a segment in this package's Cabal file that+ contains part of the specification for the package's test suite:+ .+ @+ test-suite tdd-util-tests+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ hs-source-dirs: testsrc, src+ ghc-options: -Wall -threaded+ main-is: Main.hs+ default-extensions:+ GADTs+ ,TemplateHaskell+ ,DeriveDataTypeable+ build-depends:+ …+ other-modules:+ Tests+ ,Test.Test.Util+ ,Test.Test.Util.Framework+ @+ .+ Note that @tdd-util@ is the only TDD library one needs to depend on, if one+ only uses @QuickCheck@, @HUnit@, and @test-framework@ via+ "Test.Util.Framework"; this omission is strictly optional, of course.+ .+ /Test Running Example/+ .+ Here is the output of importing @Test.Test.Util@ inside the @testsrc@+ directory and then running @tests@ on my system (note this is not the result+ of running the entire test suite; to do that, either run Main.hs or run, with+ 'defaultMain', the @tests@ exported from @Tests.hs@ rather than+ @Test.Test.Util@), without the coloured formatting:+ .+ @+ % ghci Test.Test.Util+ GHCi, version 7.6.1: http:\/\/www.haskell.org\/ghc\/ :? for help+ Loading package ghc-prim ... linking ... done.+ Loading package integer-gmp ... linking ... done.+ Loading package base ... linking ... done.+ [1 of 1] Compiling Test.Test.Util ( Test\/Test\/Util.hs, interpreted )+ Ok, modules loaded: Test.Test.Util.+ .+ \*Test.Test.Util> defaultMain tests+ Loading package pretty-1.1.1.0 ... linking ... done.+ …+ Loading package tdd-util-0.1.0.1 ... linking ... done.+ Throwing and catching exceptions - isExceptionThrown:+ throwing an exception: [OK]+ not throwing an exception: [OK]+ Throwing and catching exceptions - assert*Thrown:+ throwing an exception: [OK]+ not throwing an exception: [OK]+ isExceptionThrown -> assert*Thrown:+ Applying appropriate assert*Thrown given result of isExceptionThrown: [OK, passed 100 tests]+ Timed tests:+ timeMicroseconds:+ timeMicroseconds is accurate for random sleep times within 10ms: [OK, passed 100 tests]+ timeMicroseconds is accurate for random delay times by timeout within 10ms: [OK, passed 100 tests]+ timeoutMicroseconds behaves like timeout and throws exceptions appropriately:+ timeoutMicroseconds overflow: [OK]+ timeoutMicroseconds non-overflow: [OK]+ waiting for a random amount of time from 0ms - 600ms; measured time difference is less than 10ms: [OK, passed 100 tests]+ assertMicroseconds:+ timeoutMicroseconds -> assertMicroseconds (assert*Thrown): [OK, passed 100 tests]+ timeoutProcessMicroseconds behaves like timeoutMicroseconds and throws exceptions appropriately:+ timeoutProcessMicroseconds overflow: [OK]+ timeoutProcessMicroseconds non-overflow: [OK]+ random sleep times and timeouts; return value is appropriate (NB: requires -threaded to work properly): [OK, passed 100 tests]+ assertProcessMicroseconds:+ timeoutProcessMicroseconds -> assertProcessMicroseconds (assert*Thrown): [OK, passed 100 tests]+ .+ Properties Test Cases Total + Passed 7 8 15 + Failed 0 0 0 + Total 7 8 15 + @ category: Testing tested-with: GHC == 7.6.1
testsrc/Test/Test/Util.hs view
@@ -50,8 +50,8 @@ (\ ~() -> assertNotThrown (Nothing :: Maybe (AssertionFailed -> String)) m) =<< (isExceptionThrown m :: IO (Either AssertionFailed ())) ]- -- TODO: (See annotation.)- , testGroup "Timed tests (TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.)" $+ -- TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.+ , testGroup "Timed tests" $ [ testGroup "timeMicroseconds" $ let time process m = do forAllM (choose (0, maxDelayTime)) $ \actualUs -> do@@ -84,8 +84,8 @@ qAssert $ (abs $ us - actualUs) <= cushion ] ]- -- TODO: (See annotation.)- , testGroup "assertMicroseconds (TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.)" $+ -- TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.+ , testGroup "assertMicroseconds" $ [ testProperty "timeoutMicroseconds -> assertMicroseconds (assert*Thrown)" . monadicIO $ -- (us, cap); cap from us is greater than cushion forAllM (choose (0, maxDelayTime)) $ \us -> forAllM (choose (0, maxDelayTime) `suchThat` \cap -> abs (cap - us) > cushion) $ \cap -> do@@ -118,8 +118,8 @@ maybe True (const False) <$> timeoutProcessMicroseconds cap ph qAssert $ killed == (cap < us) ]- -- TODO: (See annotation.)- , testGroup "assertProcessMicroseconds (TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.)" $+ -- TODO: Once a means of testing a monadic property with many threads is implemented, increase maxDelayTime from 30ms to 600ms; tests may not be as reliable until then.+ , testGroup "assertProcessMicroseconds" $ [ testProperty "timeoutProcessMicroseconds -> assertProcessMicroseconds (assert*Thrown)" . monadicIO $ -- (us, cap); cap from us is greater than cushion forAllM (choose (0, maxDelayTime)) $ \us -> forAllM (choose (0, maxDelayTime) `suchThat` \cap -> abs (cap - us) > cushion) $ \cap -> do