From 4a160e34985575013311b7dca71a6c49511bf73c Mon Sep 17 00:00:00 2001 From: Ollie Charles Date: Sun, 9 Jun 2024 13:23:29 +0100 Subject: [PATCH] Rewrite tests to use `tasty` & `tasty-golden` (#159) This keeps the general shape of the test suite, but instead of using HSpec as the driver we now use tasty. The main benefit here is we can use `tasty-golden`, which makes it easier to update the golden files if the output legitimately changes. --- test/{Spec.hs => Main.hs} | 53 ++++++++++++++--------------- test/UnitTests.hs | 1 - test/UnitTests/Weeder/ConfigSpec.hs | 23 ++++++------- weeder.cabal | 12 ++++--- 4 files changed, 44 insertions(+), 45 deletions(-) rename test/{Spec.hs => Main.hs} (67%) delete mode 100644 test/UnitTests.hs diff --git a/test/Spec.hs b/test/Main.hs similarity index 67% rename from test/Spec.hs rename to test/Main.hs index 0ef150e..17dca70 100644 --- a/test/Spec.hs +++ b/test/Main.hs @@ -1,9 +1,12 @@ +module Main (main) where + import qualified Weeder.Main import qualified Weeder.Run import qualified Weeder import qualified TOML -import qualified UnitTests +import qualified UnitTests.Weeder.ConfigSpec +import Data.Maybe import Algebra.Graph.Export.Dot import GHC.Types.Name.Occurrence (occNameString) import System.Directory @@ -11,28 +14,32 @@ import System.Environment (getArgs, withArgs) import System.FilePath import System.Process import System.IO (stderr, hPrint) -import Test.Hspec +import Test.Tasty (TestTree, defaultMain, testGroup) import Control.Monad (zipWithM_, when) import Control.Exception ( throwIO, IOException, handle ) import Data.Maybe (isJust) import Data.List (find, sortOn) +import Data.ByteString (ByteString) +import qualified Data.ByteString.Lazy as LBS +import Data.Text (Text, pack) +import Data.Text.Encoding (encodeUtf8) +import Test.Tasty.Golden main :: IO () main = do - args <- getArgs testOutputFiles <- fmap sortTests discoverIntegrationTests let hieDirectories = map (dropExtension . snd) testOutputFiles - drawDots = mapM_ (drawDot . (<.> ".dot")) hieDirectories - graphviz = "--graphviz" `elem` args - withArgs (filter (/="--graphviz") args) $ - hspec $ afterAll_ (when graphviz drawDots) $ do - describe "Weeder.Run" $ - describe "runWeeder" $ - zipWithM_ (uncurry integrationTestSpec) testOutputFiles hieDirectories - UnitTests.spec + defaultMain $ + testGroup "Weeder" + [ testGroup "Weeder.Run" $ + [ testGroup "runWeeder" $ + zipWith (uncurry integrationTest) + testOutputFiles + hieDirectories + ] + , UnitTests.Weeder.ConfigSpec.tests + ] where - -- Draw a dotfile via graphviz - drawDot f = callCommand $ "dot -Tpng " ++ f ++ " -o " ++ (f -<.> ".png") -- Sort the output files such that the failing ones go last sortTests = sortOn (isJust . fst) @@ -44,18 +51,10 @@ main = do -- If @failingFile@ is @Just@, it is used as the expected output instead of -- @stdoutFile@, and a different failure message is printed if the output -- matches @stdoutFile@. -integrationTestSpec :: Maybe FilePath -> FilePath -> FilePath -> Spec -integrationTestSpec failingFile stdoutFile hieDirectory = do - it (integrationTestText ++ hieDirectory) $ do - expectedOutput <- readFile stdoutFile - actualOutput <- integrationTestOutput hieDirectory - case failingFile of - Just f -> do - failingOutput <- readFile f - actualOutput `shouldNotBe` expectedOutput - actualOutput `shouldBe` failingOutput - Nothing -> - actualOutput `shouldBe` expectedOutput +integrationTest :: Maybe FilePath -> FilePath -> FilePath -> TestTree +integrationTest failingFile stdoutFile hieDirectory = do + goldenVsString (integrationTestText ++ hieDirectory) (fromMaybe stdoutFile failingFile) $ + integrationTestOutput hieDirectory where integrationTestText = case failingFile of Nothing -> "produces the expected output for " @@ -74,7 +73,7 @@ discoverIntegrationTests = do -- | Run weeder on the given directory for .hie files, returning stdout -- Also creates a dotfile containing the dependency graph as seen by Weeder -integrationTestOutput :: FilePath -> IO String +integrationTestOutput :: FilePath -> IO LBS.ByteString integrationTestOutput hieDirectory = do hieFiles <- Weeder.Main.getHieFiles ".hie" [hieDirectory] True weederConfig <- TOML.decodeFile configExpr >>= either throwIO pure @@ -83,6 +82,6 @@ integrationTestOutput hieDirectory = do graph' = export (defaultStyle (occNameString . Weeder.declOccName)) graph handle (\e -> hPrint stderr (e :: IOException)) $ writeFile (hieDirectory <.> ".dot") graph' - pure (unlines $ map Weeder.Run.formatWeed weeds) + pure (LBS.fromStrict $ encodeUtf8 $ pack $ unlines $ map Weeder.Run.formatWeed weeds) where configExpr = hieDirectory <.> ".toml" diff --git a/test/UnitTests.hs b/test/UnitTests.hs deleted file mode 100644 index 359d26c..0000000 --- a/test/UnitTests.hs +++ /dev/null @@ -1 +0,0 @@ -{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=UnitTests #-} diff --git a/test/UnitTests/Weeder/ConfigSpec.hs b/test/UnitTests/Weeder/ConfigSpec.hs index f0c0004..adfdb43 100644 --- a/test/UnitTests/Weeder/ConfigSpec.hs +++ b/test/UnitTests/Weeder/ConfigSpec.hs @@ -1,20 +1,19 @@ -module UnitTests.Weeder.ConfigSpec (spec) where +module UnitTests.Weeder.ConfigSpec (tests) where import Weeder.Config import qualified TOML import qualified Data.Text as T -import Test.Hspec (Spec, describe, it) +import Test.Tasty.HUnit +import Test.Hspec.Expectations (shouldBe) +import Test.Tasty (TestTree, testGroup) -spec :: Spec -spec = - describe "Weeder.Config" $ - describe "configToToml" $ - it "passes prop_configToToml" prop_configToToml +tests :: TestTree +tests = + testGroup "Weeder.Config" + [ testCase "configToToml" configToTomlTests ] --- >>> prop_configToToml --- True -prop_configToToml :: Bool -prop_configToToml = +configToTomlTests :: Assertion +configToTomlTests = let cf = Config { rootPatterns = mempty , typeClassRoots = True @@ -22,4 +21,4 @@ prop_configToToml = , unusedTypes = True } cf' = T.pack $ configToToml cf - in TOML.decode cf' == Right cf + in TOML.decode cf' `shouldBe` Right cf diff --git a/weeder.cabal b/weeder.cabal index 01651d5..363b7bb 100644 --- a/weeder.cabal +++ b/weeder.cabal @@ -72,19 +72,21 @@ test-suite weeder-test , directory , filepath , ghc - , hspec , process + , tasty + , tasty-hunit-compat + , tasty-golden , text , toml-reader , weeder + , hspec-expectations + , text + , bytestring type: exitcode-stdio-1.0 - main-is: Spec.hs + main-is: Main.hs hs-source-dirs: test - autogen-modules: - Paths_weeder other-modules: Paths_weeder - UnitTests -- Tests Spec.ApplicativeDo.ApplicativeDo Spec.BasicExample.BasicExample