If the test suite is for QuickCheck, I recommend that you use the new All module instead: http://hackage.haskell.org/packages/archive/QuickCheck/2.4.1.1/doc/html/Test-QuickCheck-All.html
It does the same, except that it extracts property names by accessing the file system and analyzing the file in which the splicing is located (if you use some other test environment, you can use the same approach anyway).
If you really want to quote the entire file, you can use a quasicycler (which does not require indentation) instead. You can easily create your request for haskell-src-meta, but I advise against this approach because it will not support some Haskell functions and will probably give bad error messages.
Aggregation of test suits is a difficult problem, you can probably expand the procedure for collecting names to somehow monitor the import, but this is a lot of work. Here is a workaround:
You can use this modified version of forAllProperties :
import Test.QuickCheck import Test.QuickCheck.All import Language.Haskell.TH import Data.Char import Data.List import Control.Monad allProperties :: Q Exp -- :: [(String,Property)] allProperties = do Loc { loc_filename = filename } <- location when (filename == "<interactive>") $ error "don't run this interactively" ls <- runIO (fmap lines (readFile filename)) let prefixes = map (takeWhile (\c -> isAlphaNum c || c == '_') . dropWhile (\c -> isSpace c || c == '>')) ls idents = nubBy (\xy -> snd x == snd y) (filter (("prop_" `isPrefixOf`) . snd) (zip [1..] prefixes)) quickCheckOne :: (Int, String) -> Q [Exp] quickCheckOne (l, x) = do exists <- return False `recover` (reify (mkName x) >> return True) if exists then sequence [ [| ($(stringE $ x ++ " on " ++ filename ++ ":" ++ show l), property $(mono (mkName x))) |] ] else return [] [|$(fmap (ListE . concat) (mapM quickCheckOne idents)) |]
You also need the runQuickCheckAll function, which is not exported from All:
runQuickCheckAll :: [(String, Property)] -> (Property -> IO Result) -> IO Bool runQuickCheckAll ps qc = fmap and . forM ps $ \(xs, p) -> do putStrLn $ "=== " ++ xs ++ " ===" r <- qc p return $ case r of Success { } -> True Failure { } -> False NoExpectedFailure { } -> False
In each test module, you now define
propsN = $allProperties
where N is the number or other unique identifier (or you can use the same name and use the qualified names in the step below).
In your main test suite, you define
props :: [(String,Property)] props = concat [props1, props2 ... propsN]
If you really want to avoid adding a list member for each module, you can make a TH script that generates this list.
To run all your tests just say
runTests = runQuickCheckAll quickCheckResult props