packages feed

tasty-discover 3.0.2 → 4.0.0

raw patch · 11 files changed

+314/−158 lines, 11 filesdep +Globdep +hedgehogdep +tasty-hedgehogPVP ok

version bump matches the API change (PVP)

Dependencies added: Glob, hedgehog, tasty-hedgehog

API changes (from Hackage documentation)

- Test.Tasty.Discover: addSuffixes :: [String] -> [String]
- Test.Tasty.Discover: extractTests :: FilePath -> String -> [Test]
- Test.Tasty.Discover: filesBySuffix :: FilePath -> [String] -> IO [FilePath]
- Test.Tasty.Discover: ingredientImport :: String -> String
- Test.Tasty.Discover: ingredients :: [String] -> String
- Test.Tasty.Discover: isHidden :: FilePath -> Bool
- Test.Tasty.Discover: isIgnored :: [FilePath] -> String -> Bool
- Test.Tasty.Discover: showImports :: [String] -> String
- Test.Tasty.Discover: showModuleTree :: ModuleTree -> [String]
- Test.Tasty.Discover: testFileSuffixes :: Config -> [String]
+ Test.Tasty.Config: [ignores] :: Config -> Maybe GlobPattern
+ Test.Tasty.Config: [modules] :: Config -> Maybe GlobPattern
+ Test.Tasty.Config: type GlobPattern = String
- Test.Tasty.Config: Config :: Maybe String -> Maybe String -> [FilePath] -> [Ingredient] -> Bool -> Bool -> Bool -> Config
+ Test.Tasty.Config: Config :: Maybe GlobPattern -> Maybe String -> Maybe String -> Maybe GlobPattern -> [FilePath] -> [Ingredient] -> Bool -> Bool -> Bool -> Config

Files

CHANGELOG.md view
@@ -8,6 +8,20 @@ [Keep a Changelog]: http://keepachangelog.com/ [Semantic Versioning]: http://semver.org/ +# 4.0.0 [2017-09-01]++## Changed+- Deprecated `--[no-]module-suffix` for `--modules` (see pull request [#117]).+- Deprecated `--ignore-module` for `--ignores` (see pull request [#117]).++## Added+- `tasty-hedgehog` is now a supported test library.++## Removed+- `unit_` prefixes have been removed.++[#117]: https://github.com/lwm/tasty-discover/pull/117+ # 3.0.2 [2017-06-05]  ### Fixed
README.md view
@@ -11,24 +11,73 @@  # Getting Started -5 steps to tasty test discovery satori:-  - Create a `Tasty.hs` in the `hs-source-dirs` of your test suite.-  - Set your test suite `main-is` to the `Tasty.hs`.-  - Create test modules in files with suffix `*Test.hs` or `*Spec.hs`.-  - Write your tests with the following prefixes:-    - `prop_`: [QuickCheck](http://hackage.haskell.org/package/tasty-quickcheck) properties.-    - `scprop_`: [SmallCheck](http://hackage.haskell.org/package/tasty-smallcheck) properties.-    - `unit_`: [HUnit](http://hackage.haskell.org/package/tasty-hunit) test cases.-    - `spec_`: [Hspec](http://hackage.haskell.org/package/tasty-hspec) specifications.-    - `test_`: [Tasty](http://hackage.haskell.org/package/tasty) TestTrees.+There's 4 simple steps: -# Examples+  1. [Create a test driver file in the test directory](#create-test-driver-file)+  2. [Mark the driver file as the `main-is` in the test suite](#configure-cabal-test-suite)+  3. [Mark tests with the correct prefixes](#write-tests)+  4. [Customise test discovery as needed](#customise-discovery) +Check out the [example project](#example-project) to get moving quickly.++## Create Test Driver File++You can name this file anything you want but it must contain the correct+preprocessor definition for tasty-discover to run and also, to detect the+configuration. It should be in the top level of the test directory.++For example (in `test/Driver.hs`):++```+{-# OPTIONS_GHC -F -pgmF tasty-discover #-}+```++## Configure Cabal Test Suite++In order for Cabal/Stack to know where the tests are, you'll need to configure+the main-is option of your test-suite to point to that file. In the following+example, the test driver file is called Driver.hs:++```+test-suite test+  main-is: Driver.hs+  hs-source-dirs: tests+  build-depends: base+```++If you use [hpack], that might look like:++[hpack]: https://github.com/sol/hpack++``` yaml+tests:+  test:+    main: "Driver.hs"+    source-dirs: "test"+    dependencies:+    - "base"+```++# Write Tests++Create test modules and correctly prefix the tests with the name that+corresponds to the testing library you wish to run the test with:++  - **prop_**: [QuickCheck](http://hackage.haskell.org/package/tasty-quickcheck) properties.+  - **scprop_**: [SmallCheck](http://hackage.haskell.org/package/tasty-smallcheck) properties.+  - **hprop_**: [Hedgehog](http://hackage.haskell.org/package/tasty-hedgehog) properties.+  - **unit_**: [HUnit](http://hackage.haskell.org/package/tasty-hunit) test cases.+  - **spec_**: [Hspec](http://hackage.haskell.org/package/tasty-hspec) specifications.+  - **test_**: [Tasty](http://hackage.haskell.org/package/tasty) TestTrees.++Here's an example test module:+ ``` haskell {-# LANGUAGE ScopedTypeVariables #-}  module ExampleTest where +import Data.List import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.Hspec@@ -70,43 +119,53 @@   pure $ map (\s -> testCase s $ pure ()) inputs ``` -# Configuration--Pass configuration options within your `Tasty.hs` like so:+# Customise Discovery -``` haskell-{-#- OPTIONS_GHC -F -pgmF tasty-discover- -optF <OPTION>- -optF <OPTION>- -- etc.-#-}-```+You configure tasty-discover by passing options to the test driver file.  ## No Arguments+ Example: `{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --debug #-}` -  - `--no-module-suffix`: Collect all test modules, regardless of module suffix.-  - `--debug`: Output the contents of the generated module while testing.-  - `--tree-display`: Display the test output results hierarchically.+  - **--debug**: Output the contents of the generated module while testing.+  - **--tree-display**: Display the test output results hierarchically.  ## With Arguments-Example: `{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --module-suffix=FooBar #-}` -  - `--module-suffix`: Which test module suffix you wish to have discovered.-  - `--generated-module`: The name of the generated test module.-  - `--ignore-module`: Which test modules to ignore from discovery.-  - `--ingredient`: Tasty ingredients to add to your test runner.+Example: `{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --modules="*CustomTest.hs" #-}` +  - **--modules**: Which test modules to discover (with glob pattern).+  - **--ignores**: Which test modules to ignore (with glob pattern).+  - **--generated-module**: The name of the generated test module.+  - **--ingredient**: Tasty ingredients to add to your test runner.++# Example Project++See the [testing for this package] for a fully configured example.++[testing for this package]: https://github.com/lwm/tasty-discover/tree/master/test+ # Change Log-See the [change log] for the latest changes. +Please see the [CHANGELOG.md] for the latest changes.++[CHANGELOG.md]: https://github.com/lwm/tasty-discover/blob/master/CHANGELOG.md++# Deprecation Policy++If a breaking change is implemented, you'll see a major version increase, an+entry in the [change log] and a compile time error with a deprecation warning+and clear instructions on how to upgrade. Please do complain if we're doing+this too much.+ [change log]: https://github.com/lwm/tasty-discover/blob/master/CHANGELOG.md  # Contributing+ All contributions welcome!  # Acknowledgements+ Thanks to [hspec-discover] and [tasty-auto] for making this possible.  [hspec-discover]: https://hspec.github.io/hspec-discover.html
executable/Main.hs view
@@ -1,4 +1,5 @@ -- | Main executable module.+ module Main where  import           Control.Monad       (when)
library/Test/Tasty/Config.hs view
@@ -1,7 +1,17 @@--- Configuration options module.-module Test.Tasty.Config-  ( Config(..)+-- | The test driver configuration options module.+--+-- Anything that can be passed as an argument to the test driver+-- definition exists as a field in the 'Config' type.++module Test.Tasty.Config (+  -- * Configuration Options+  Config (..)+  , GlobPattern++  -- * Configuration Parser   , parseConfig++  -- * Configuration Defaults   , defaultConfig   ) where @@ -10,32 +20,64 @@                                         ArgOrder (Permute), OptDescr (Option),                                         getOpt) +-- | A tasty ingredient. type Ingredient = String +-- | A glob pattern.+type GlobPattern = String++-- | The discovery and runner configuration. data Config = Config-  { moduleSuffix        :: Maybe String-  , generatedModuleName :: Maybe String-  , ignoredModules      :: [FilePath]-  , tastyIngredients    :: [Ingredient]-  , noModuleSuffix      :: Bool-  , debug               :: Bool-  , treeDisplay         :: Bool+  { modules             :: Maybe GlobPattern -- ^ Glob pattern for matching modules during test discovery.+  , moduleSuffix        :: Maybe String      -- ^ <<<DEPRECATED>>>: Module suffix.+  , generatedModuleName :: Maybe String      -- ^ Name of the generated main module.+  , ignores             :: Maybe GlobPattern -- ^ Glob pattern for ignoring modules during test discovery.+  , ignoredModules      :: [FilePath]        -- ^ <<<DEPRECATED>>>: Ignored modules by full name.+  , tastyIngredients    :: [Ingredient]      -- ^ Tasty ingredients to use.+  , noModuleSuffix      :: Bool              -- ^ <<<DEPRECATED>>>: suffix and look in all modules.+  , debug               :: Bool              -- ^ Debug the generated module.+  , treeDisplay         :: Bool              -- ^ Tree display for the test results table.   } deriving (Show)  -- | The default configuration defaultConfig :: Config-defaultConfig = Config Nothing Nothing [] [] False False False+defaultConfig = Config Nothing Nothing Nothing Nothing [] [] False False False +-- | Deprecation message for old `--[no-]module-suffix` option.+moduleSuffixDeprecationMessage :: String+moduleSuffixDeprecationMessage =+  error $ concat+    [ "\n\n"+    , "----------------------------------------------------------\n"+    , "DEPRECATION NOTICE: `--[no-]module-suffix` is deprecated.\n"+    , "The default behaviour now discovers all test module suffixes.\n"+    , "Please use the `--modules='<glob-pattern>'` option to specify.\n"+    , "----------------------------------------------------------\n"+    ]++-- | Deprecation message for old `--ignore-module` option.+ignoreModuleDeprecationMessage :: String+ignoreModuleDeprecationMessage =+  error $ concat+    [ "\n\n"+    , "----------------------------------------------------------\n"+    , "DEPRECATION NOTICE: `--ignore-module` is deprecated.\n"+    , "Please use the `--ignores='<glob-pattern>'` option instead.\n"+    , "----------------------------------------------------------\n"+    ]+ -- | Configuration options parser. parseConfig :: String -> [String] -> Either String Config parseConfig prog args = case getOpt Permute options args of     (opts, [], []) ->-      let config   = foldl (flip id) defaultConfig opts-          errorMsg = "You cannot combine '--no-module-suffix' and '--module-suffix'\n"-      in-        if noModuleSuffix config && isJust (moduleSuffix config)-        then formatError errorMsg-        else Right config+      let config = foldl (flip id) defaultConfig opts in+        if noModuleSuffix config || isJust (moduleSuffix config) then+          error moduleSuffixDeprecationMessage+        else+        if not $ null (ignoredModules config) then+          error ignoreModuleDeprecationMessage+        else+        Right config     (_, _, err:_)  -> formatError err     (_, arg:_, _)  -> formatError ("unexpected argument `" ++ arg ++ "`\n")   where@@ -44,21 +86,27 @@ -- | All configuration options. options :: [OptDescr (Config -> Config)] options = [-    Option [] ["module-suffix"]+    Option [] ["modules"]+      (ReqArg (\s c -> c {modules = Just s}) "GLOB-PATTERN")+      "Specify desired modules with a glob pattern (white-list)"+  , Option [] ["module-suffix"]       (ReqArg (\s c -> c {moduleSuffix = Just s}) "SUFFIX")-      "Specify desired test module suffix"+      "<<<DEPRECATED>>>: Specify desired test module suffix"   , Option [] ["generated-module"]       (ReqArg (\s c -> c {generatedModuleName = Just s}) "MODULE")       "Qualified generated module name"+  , Option [] ["ignores"]+      (ReqArg (\s c -> c {ignores = Just s}) "GLOB-PATTERN")+      "Specify desired modules to ignore with a glob pattern (black-list)"   , Option [] ["ignore-module"]       (ReqArg (\s c -> c {ignoredModules = s : ignoredModules c}) "FILE")-      "Ignore a test module"+      "<<<DEPRECATED>>>: Ignore a test module"   , Option [] ["ingredient"]       (ReqArg (\s c -> c {tastyIngredients = s : tastyIngredients c}) "INGREDIENT")       "Qualified tasty ingredient name"   , Option [] ["no-module-suffix"]       (NoArg $ \c -> c {noModuleSuffix = True})-      "Ignore test module suffix and import them all"+      "<<<DEPRECATED>>>: Ignore test module suffix and import them all"   , Option [] ["debug"]       (NoArg $ \c -> c {debug = True})       "Debug output of generated test module"
library/Test/Tasty/Discover.hs view
@@ -1,16 +1,28 @@ -- | Automatic test discovery and runner for the tasty framework.-module Test.Tasty.Discover where +module Test.Tasty.Discover (+  -- * Main Test Generator+  generateTestDriver++  -- * For Testing Purposes Only+  , ModuleTree (..)+  , findTests+  , mkModuleTree+  , showTests+  ) where+ import           Data.List            (dropWhileEnd, intercalate, isPrefixOf,-                                       isSuffixOf, nub)+                                       nub) import qualified Data.Map.Strict      as M-import           Data.Traversable     (for)-import           System.Directory     (doesDirectoryExist, getDirectoryContents)-import           System.FilePath      (takeDirectory, (</>))-import           Test.Tasty.Config    (Config (..))+import           Data.Maybe           (fromMaybe)+import           System.FilePath      (takeDirectory, takeFileName, (</>))+import           System.FilePath.Glob (compile, globDir1, match)+import           Test.Tasty.Config    (Config (..), GlobPattern) import           Test.Tasty.Generator (Generator (..), Test (..), generators,                                        getGenerators, mkTest, showSetup) +-- | Main function generator, along with all the boilerplate which+-- which will run the discovered tests. generateTestDriver :: Config -> String -> [String] -> FilePath -> [Test] -> String generateTestDriver config modname is src tests =   let generators' = getGenerators tests@@ -40,38 +52,29 @@         ]       ] -addSuffixes :: [String] -> [String]-addSuffixes modules = (++) <$> modules <*> [".lhs", ".hs"]--isHidden :: FilePath -> Bool-isHidden filename = head filename /= '.'--filesBySuffix :: FilePath -> [String] -> IO [FilePath]-filesBySuffix dir suffixes = do-  entries <- filter isHidden <$> getDirectoryContents dir-  fmap concat $ for entries $ \entry -> do-    let dir' = dir </> entry-    dirExists <- doesDirectoryExist dir'-    if dirExists then-      map (entry </>) <$> filesBySuffix dir' suffixes-    else if any (`isSuffixOf` entry) suffixes then-      pure [entry]-    else-      pure []+-- | Match files by specified glob pattern.+filesByModuleGlob :: FilePath -> Maybe GlobPattern -> IO [String]+filesByModuleGlob directory globPattern = do+  (fmap takeFileName) <$> globDir1 pattern directory+  where pattern = compile (fromMaybe "*.hs*" globPattern) -isIgnored :: [FilePath] -> String -> Bool-isIgnored ignores filename = filename `notElem` addSuffixes ignores+-- | Filter and remove files by specified glob pattern.+ignoreByModuleGlob :: [FilePath] -> Maybe GlobPattern -> [FilePath]+ignoreByModuleGlob directories ignoreGlob = filter (not . match pattern) directories+  where pattern = compile (fromMaybe "" ignoreGlob) +-- | Discover the tests modules. findTests :: FilePath -> Config -> IO [Test] findTests src config = do-  let dir      = takeDirectory src-      suffixes = testFileSuffixes config-      ignores  = ignoredModules config-  files <- filter (isIgnored ignores) <$> filesBySuffix dir suffixes-  concat <$> traverse (extract dir) files+  let directory = takeDirectory src+  allModules <- filesByModuleGlob directory (modules config)+  let filtered = ignoreByModuleGlob allModules (ignores config)+  concat <$> traverse (extract directory) filtered   where-    extract dir file = extractTests file <$> readFile (dir </> file)+    extract directory file = do+      extractTests file <$> readFile (directory </> file) +-- | Extract the test names from discovered modules. extractTests :: FilePath -> String -> [Test] extractTests file = mkTestDeDuped . isKnownPrefix . parseTest   where@@ -80,24 +83,19 @@     checkPrefix g = (`isPrefixOf` g) . generatorPrefix     parseTest     = map fst . concatMap lex . lines -testFileSuffixes :: Config -> [String]-testFileSuffixes config = if noModuleSuffix config-    then [""]-    else addSuffixes suffixes-  where-    suffixes = case moduleSuffix config of-      Just suffix' -> [suffix']-      Nothing      -> ["Spec", "Test"]-+-- | Show the imports. showImports :: [String] -> String showImports mods = unlines $ nub $ map (\m -> "import qualified " ++ m ++ "\n") mods +-- | Retrieve the ingredient name. ingredientImport :: String -> String ingredientImport = init . dropWhileEnd (/= '.') +-- | Ingredients to be included. ingredients :: [String] -> String ingredients is = concat $ map (++":") is ++ ["T.defaultIngredients"] +-- | Show the tests. showTests :: Config -> [Test] -> [String] -> [String] showTests config tests testNumVars = if treeDisplay config   then showModuleTree $ mkModuleTree tests testNumVars
library/Test/Tasty/Generator.hs view
@@ -1,11 +1,26 @@+-- | The test generator boilerplate module.+--+-- Any test that is supported (HUnit, HSpec, etc.) provides here, a+-- generator type with all the context necessary for outputting the+-- necessary boilerplate for the generated main function that will+-- run all the tests.+ module Test.Tasty.Generator-  ( Generator(..)+  (+  -- * Types+  Generator (..)+  , Test (..)++  -- * Generators   , generators-  , showSetup   , getGenerator   , getGenerators-  , Test(..)-  , mkTest,++  -- * Boilerplate Formatter+  , showSetup++  -- * Type Constructor+  , mkTest   ) where  import           Data.Function   (on)@@ -13,33 +28,40 @@ import           Data.Maybe      (fromJust) import           System.FilePath (dropExtension, pathSeparator) +-- | The test type. data Test = Test-  { testModule   :: String-  , testFunction :: String+  { testModule   :: String -- ^ Module name.+  , testFunction :: String -- ^ Function name.   } deriving (Eq, Show) +-- | 'Test' constructor. mkTest :: FilePath -> String -> Test mkTest = Test . chooser pathSeparator '.' . dropExtension   where chooser c1 c2 = map $ \c3 -> if c3 == c1 then c2 else c3 +-- | The generator type. data Generator = Generator-  { generatorPrefix :: String-  , generatorImport :: String-  , generatorClass  :: String-  , generatorSetup  :: Test -> String+  { generatorPrefix :: String          -- ^ Generator prefix.+  , generatorImport :: String          -- ^ Module import path.+  , generatorClass  :: String          -- ^ Generator class.+  , generatorSetup  :: Test -> String  -- ^ Generator setup.   } +-- | Module import qualifier. qualifyFunction :: Test -> String qualifyFunction t = testModule t ++ "." ++ testFunction t +-- | Function namer. name :: Test -> String name = chooser '_' ' ' . tail . dropWhile (/= '_') . testFunction   where chooser c1 c2 = map $ \c3 -> if c3 == c1 then c2 else c3 +-- | Generator retriever (single). getGenerator :: Test -> Generator getGenerator t = fromJust $ getPrefix generators   where getPrefix = find ((`isPrefixOf` testFunction t) . generatorPrefix) +-- | Generator retriever (many). getGenerators :: [Test] -> [Generator] getGenerators =   map head .@@ -47,19 +69,31 @@   sortOn generatorPrefix .   map getGenerator +-- | Boilerplate formatter. showSetup :: Test -> String -> String showSetup t var = "  " ++ var ++ " <- " ++ setup ++ "\n"   where setup = generatorSetup (getGenerator t) t +-- | All types of tests supported for boilerplate generation. generators :: [Generator] generators =   [ quickCheckPropertyGenerator-  , hunitTestCaseGeneratorDeprecated+  , hedgehogPropertyGenerator   , hunitTestCaseGenerator   , hspecTestCaseGenerator   , tastyTestGroupGenerator   ] +-- | Quickcheck group generator prefix.+hedgehogPropertyGenerator :: Generator+hedgehogPropertyGenerator = Generator+  { generatorPrefix = "hprop_"+  , generatorImport = "import qualified Test.Tasty.Hedgehog as H\n"+  , generatorClass  = ""+  , generatorSetup  = \t -> "pure $ H.testProperty \"" ++ name t ++ "\" " ++ qualifyFunction t+  }++-- | Quickcheck group generator prefix. quickCheckPropertyGenerator :: Generator quickCheckPropertyGenerator = Generator   { generatorPrefix = "prop_"@@ -68,26 +102,7 @@   , generatorSetup  = \t -> "pure $ QC.testProperty \"" ++ name t ++ "\" " ++ qualifyFunction t   } -deprecationMessage :: String-deprecationMessage =-  error $ concat-    [ "\n\n"-    , "----------------------------------------------------------\n"-    , "DEPRECATION NOTICE: The `case_` prefix is deprecated.\n"-    , "Please use the `unit_` prefix instead.\n"-    , "Please see https://github.com/lwm/tasty-discover/issues/95.\n"-    , "----------------------------------------------------------\n"-    ]---- DEPRECATED: Use `unit_` instead (below)-hunitTestCaseGeneratorDeprecated :: Generator-hunitTestCaseGeneratorDeprecated = Generator-  { generatorPrefix = "case_"-  , generatorImport = deprecationMessage-  , generatorClass  = deprecationMessage-  , generatorSetup  = const deprecationMessage-  }-+-- | HUnit generator prefix. hunitTestCaseGenerator :: Generator hunitTestCaseGenerator = Generator   { generatorPrefix = "unit_"@@ -101,6 +116,7 @@   , generatorSetup  = \t -> "testCase \"" ++ name t ++ "\" " ++ qualifyFunction t   } +-- | Hspec generator prefix. hspecTestCaseGenerator :: Generator hspecTestCaseGenerator = Generator   { generatorPrefix = "spec_"@@ -109,6 +125,7 @@   , generatorSetup  = \t -> "HS.testSpec \"" ++ name t ++ "\" " ++ qualifyFunction t   } +-- | Tasty group generator prefix. tastyTestGroupGenerator :: Generator tastyTestGroupGenerator = Generator   { generatorPrefix = "test_"
tasty-discover.cabal view
@@ -1,9 +1,9 @@--- This file has been generated from package.yaml by hpack version 0.17.0.+-- This file has been generated from package.yaml by hpack version 0.18.1. -- -- see: https://github.com/sol/hpack  name:           tasty-discover-version:        3.0.2+version:        4.0.0 synopsis:       Test discovery for the tasty framework. description:    Automatic test discovery and runner for the tasty framework.                 Prefix your test case names and tasty-discover will discover, collect and run them. All popular test libraries are covered. Configure once and then just write your tests. Avoid forgetting to add test modules to your Cabal/Hpack files. Tasty ingredients are included along with various configuration options for different use cases. Please see the `README.md` below for how to get started.@@ -36,10 +36,13 @@     , containers >= 0.4 && < 1.0     , directory  >= 1.1 && < 2.0     , filepath   >= 1.3 && < 2.0+    , Glob       >= 0.8 && < 1.0   exposed-modules:       Test.Tasty.Config       Test.Tasty.Discover       Test.Tasty.Generator+  other-modules:+      Paths_tasty_discover   default-language: Haskell2010  executable tasty-discover@@ -50,12 +53,13 @@     , containers >= 0.4 && < 1.0     , directory  >= 1.1 && < 2.0     , filepath   >= 1.3 && < 2.0+    , Glob       >= 0.8 && < 1.0     , tasty-discover   default-language: Haskell2010  test-suite test   type: exitcode-stdio-1.0-  main-is: Tasty.hs+  main-is: Driver.hs   hs-source-dirs:       test   ghc-options: -Wall@@ -64,6 +68,7 @@     , containers >= 0.4 && < 1.0     , directory  >= 1.1 && < 2.0     , filepath   >= 1.3 && < 2.0+    , Glob       >= 0.8 && < 1.0     , base     , tasty     , tasty-discover@@ -71,6 +76,8 @@     , tasty-hunit     , tasty-quickcheck     , tasty-smallcheck+    , tasty-hedgehog+    , hedgehog   other-modules:       ConfigTest       DiscoverTest
test/ConfigTest.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+ module ConfigTest where  import           Data.List             (isInfixOf)@@ -8,50 +9,52 @@                                         generateTestDriver, mkModuleTree,                                         showTests) import           Test.Tasty.Generator  (Test (..), mkTest)+import           Test.Tasty.Hspec import           Test.Tasty.HUnit import           Test.Tasty.QuickCheck -unit_noModuleSuffixEmptyList :: IO ()-unit_noModuleSuffixEmptyList = do-  actual <- findTests "test/SubMod/" (defaultConfig { moduleSuffix = Just "DoesntExist"})-  actual @?= []--unit_differentGeneratedModule :: Assertion-unit_differentGeneratedModule = assertBool "" ("FunkyModuleName" `isInfixOf` generatedModule)-  where generatedModule = generateTestDriver defaultConfig "FunkyModuleName" [] "test/" []--unit_ignoreAModule :: IO ()-unit_ignoreAModule = do-  actual <- findTests "test/SubMod/" (defaultConfig { ignoredModules = ["PropTest"] })-  actual @?= []+spec_modules :: Spec+spec_modules =+  describe "Test discovery" $+  it "Discovers tests" $ do+    let expectedTest = mkTest "PropTest" "prop_additionAssociative"+        config       = defaultConfig { modules = Just "*Test.hs" }+    discoveredTests <- findTests "test/SubMod/" config+    discoveredTests `shouldBe` [expectedTest] -unit_noModuleSuffix :: IO ()-unit_noModuleSuffix  = do-  actual1 <- findTests "test/SubMod/" defaultConfig-  actual1 @?= [mkTest "PropTest" "prop_additionAssociative"]+spec_ignores :: Spec+spec_ignores =+  describe "Module ignore configuration" $+  it "Ignores tests in modules with the specified suffix" $ do+    let ignoreModuleConfig = defaultConfig { ignores = Just "*.hs" }+    discoveredTests <- findTests "test/SubMod/" ignoreModuleConfig+    discoveredTests `shouldBe` [] -  actual2 <- findTests "test/SubMod/" (defaultConfig { noModuleSuffix = True })-  let expected = [ mkTest "FooBaz" "prop_additionCommutative"-                 , mkTest "FooBaz" "prop_multiplationDistributiveOverAddition"-                 , mkTest "PropTest" "prop_additionAssociative" ]-  assertBool "" $ all (`elem` expected) actual2+spec_badModuleGlob :: Spec+spec_badModuleGlob =+  describe "Module suffix configuration" $+  it "Filters discovered tests by specified suffix" $ do+    let badGlobConfig = defaultConfig { modules = Just "DoesntExist*.hs" }+    discoveredTests <- findTests "test/SubMod/" badGlobConfig+    discoveredTests `shouldBe` [] -unit_noModuleSuffixRecurseDirs :: IO ()-unit_noModuleSuffixRecurseDirs = do-  tests <- findTests "test/" (defaultConfig { noModuleSuffix = True })-  assertBool "" $ elem (mkTest "SubMod/FooBaz" "prop_additionCommutative") tests+spec_customModuleName :: Spec+spec_customModuleName =+  describe "Module name configuration" $+  it "Creates a generated main function with the specified name" $ do+    let generatedModule = generateTestDriver defaultConfig "FunkyModuleName" [] "test/" []+    "FunkyModuleName" `shouldSatisfy` (`isInfixOf` generatedModule)  unit_noTreeDisplayDefault :: IO () unit_noTreeDisplayDefault = do-  let config = defaultConfig { noModuleSuffix = True }-  tests <- findTests "test/SubMod/" config+  tests <- findTests "test/SubMod/" defaultConfig   let testNumVars = map (('t' :) . show) [(0::Int)..]-      trees = showTests config tests testNumVars+      trees = showTests defaultConfig tests testNumVars   length trees @?= 3  unit_treeDisplay :: IO () unit_treeDisplay = do-  let config = defaultConfig { noModuleSuffix = True, treeDisplay = True }+  let config = defaultConfig { treeDisplay = True }   tests <- findTests "test/SubMod/" config   let testNumVars = map (('t' :) . show) [(0::Int)..]       trees = showTests config tests testNumVars
test/DiscoverTest.hs view
@@ -3,6 +3,9 @@ module DiscoverTest where  import           Data.List+import qualified Hedgehog              as H+import qualified Hedgehog.Gen          as Gen+import qualified Hedgehog.Range        as Range import           Test.Tasty import           Test.Tasty.Hspec import           Test.Tasty.HUnit@@ -41,3 +44,9 @@ test_generateTrees = do   inputs <- pure ["First input", "Second input"]   pure $ map (\s -> testCase s $ pure ()) inputs++{-# ANN hprop_reverse "HLint: ignore Avoid reverse" #-}+hprop_reverse :: H.Property+hprop_reverse = H.property $ do+  xs <- H.forAll $ Gen.list (Range.linear 0 100) Gen.alpha+  reverse (reverse xs) H.=== xs
+ test/Driver.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF tasty-discover #-}
− test/Tasty.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF tasty-discover #-}