diff --git a/CHANGELOG.md b/CHANGELOG.md index 000aadf..15de7f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changes -## Version 1.0.0 +## Version 0.1.0.0 _2024-12-17_ diff --git a/README.md b/README.md index 98d7567..4560435 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,4 @@ A library providing additional golden test helpers for the the output of functions that return textual output and instances of @Show@, @ToJSON@ or @ToYAML@. -To find out what's new, read the **[change log][]**. - -[change log]: https://github.com/bellroy/tasty-golden-extra/blob/master/CHANGELOG.md +To find out what's new, read the [change log](https://github.com/bellroy/tasty-golden-extra/blob/master/CHANGELOG.md). diff --git a/src/Test/Tasty/Golden/Extra/GoldenVsShow.hs b/src/Test/Tasty/Golden/Extra/GoldenVsShow.hs index d4ca05d..a31f6d7 100644 --- a/src/Test/Tasty/Golden/Extra/GoldenVsShow.hs +++ b/src/Test/Tasty/Golden/Extra/GoldenVsShow.hs @@ -30,8 +30,8 @@ import Text.Show.Pretty (ppShow) -- import System.FilePath ((\)) -- import Test.Tasty.Golden.Extra.GoldenVsShow (GoldenVsShow (..)) -- --- tasty_FromJSON_ToJSON :: GoldenVsShow --- tasty_FromJSON_ToJSON = +-- tasty_GoldenVsShow :: GoldenVsShow +-- tasty_GoldenVsShow = -- GoldenVsShow (goldenFilesPath \ "Person.golden.txt") $ -- Aeson.eitherDecodeFileStrict @Person (goldenFilesPath \ "Person.json") -- @ @@ -50,7 +50,7 @@ instance Discover.Tasty GoldenVsShow where -- import MySchemasWithShowAndShowInstances.Person (Person) -- import Data.Aeson qualified as Aeson -- import System.FilePath ((\)) --- import Test.Tasty.Golden.Extra.GoldenVsShow (GoldenVsShow (..)) +-- import Test.Tasty.Golden.Extra.GoldenVsShow (goldenVsShow) -- -- test_Show :: TestTree -- test_Show = do @@ -58,7 +58,7 @@ instance Discover.Tasty GoldenVsShow where -- goldenVsShow -- "Test Show instance for Person" -- (goldenFilesPath \ "Person.golden.txt") --- (Aeson.decodeFileStrict' inputFile) +-- (Aeson.decodeFileStrict' @Person inputFile) -- @ goldenVsShow :: (Show a) => diff --git a/src/Test/Tasty/Golden/Extra/GoldenVsString.hs b/src/Test/Tasty/Golden/Extra/GoldenVsString.hs index 8bb84eb..424a075 100644 --- a/src/Test/Tasty/Golden/Extra/GoldenVsString.hs +++ b/src/Test/Tasty/Golden/Extra/GoldenVsString.hs @@ -8,7 +8,11 @@ -- -- These helpers are useful for creating golden tests for functions that -- produce textual output. -module Test.Tasty.Golden.Extra.GoldenVsString (GoldenVsString (..)) where +module Test.Tasty.Golden.Extra.GoldenVsString + ( GoldenVsString (..), + goldenVsString, + ) +where import Data.ByteString.Lazy (ByteString) import Test.Tasty.Discover qualified as Discover @@ -20,9 +24,8 @@ import Test.Tasty.Golden -- Example use: -- -- @ --- import MySchemasWithShowAndToJSONInstances.Person (Person, convertToCSVText) +-- import MySchemasWithShowAndToJSONInstances.Person (convertToCSVText) -- import Data.Aeson qualified as Aeson --- import Data.Aeson.Encode.Pretty qualified as AesonPretty -- import System.FilePath ((\)) -- import Test.Tasty.Golden.Extra.GoldenVsString (GoldenVsString (..)) -- diff --git a/src/Test/Tasty/Golden/Extra/GoldenVsToJSON.hs b/src/Test/Tasty/Golden/Extra/GoldenVsToJSON.hs index 8dea13c..e288998 100644 --- a/src/Test/Tasty/Golden/Extra/GoldenVsToJSON.hs +++ b/src/Test/Tasty/Golden/Extra/GoldenVsToJSON.hs @@ -9,7 +9,6 @@ -- These helpers are useful for creating golden tests for @ToJSON@ instances. module Test.Tasty.Golden.Extra.GoldenVsToJSON ( GoldenVsToJSON (..), - goldenVsToJsonFile, goldenVsToJson, ) where @@ -20,7 +19,7 @@ import Data.ByteString.Lazy qualified as BL import Test.Tasty (TestName, TestTree) import Test.Tasty.Discover qualified as Discover import Test.Tasty.Golden.Advanced (goldenTest) -import Test.Tasty.Golden.Extra.Internal (assertJsonEqual) +import Test.Tasty.Golden.Extra.Internal (checkJsonDifference, maybeDifference) -- | Tasty-discoverable type for creating golden tests for @ToJSON@ instances. -- @@ -42,43 +41,6 @@ data GoldenVsToJSON = forall a. (Aeson.ToJSON a) => GoldenVsToJSON FilePath (IO instance Discover.Tasty GoldenVsToJSON where tasty info (GoldenVsToJSON ref act) = pure $ goldenVsToJson (Discover.nameOf info) ref act --- | Helper function for creating a @TestTree@ for @ToJSON@ golden tests. --- Use when you want to test code that produces a JSON file as a side effect. --- --- Example use: --- --- @ --- import MySchemasWithToJSONInstances.Person (Person, gen) --- import Data.Aeson qualified as Aeson --- import System.FilePath ((\)) --- import Test.Tasty.Golden.Extra.GoldenVsToJSON (GoldenVsToJSON (..)) --- --- test_ToJSON :: TestTree --- test_ToJSON = do --- person <- gen --- let outputFile = goldenFilesPath \ "Person.json" --- goldenVsToJSONFile --- "Test ToJSON instance for Person" --- (goldenFilesPath \ "Person.golden.json") --- outputFile --- (Aeson.encodeFile outputFile person) --- @ -goldenVsToJsonFile :: - -- | test name - TestName -> - -- | path to the «golden» file (the file that contains correct output) - FilePath -> - -- | path to the output file - FilePath -> - -- | action that creates the output file - IO () -> - TestTree -goldenVsToJsonFile name ref new act = - goldenVsToJson @Aeson.Value name ref $ do - act - eJson <- Aeson.decodeFileStrict new - orFailTest ("Couldn't decode JSON file: " <> new) eJson - -- | Helper function for creating a @TestTree@ for @ToJSON@ golden tests. -- Use when you want to test @ToJSON@ instances against a golden example on disk. -- @@ -88,7 +50,7 @@ goldenVsToJsonFile name ref new act = -- import MySchemasWithToJSONInstances.Person (Person) -- import Data.Aeson qualified as Aeson -- import System.FilePath ((\)) --- import Test.Tasty.Golden.Extra.GoldenVsToJSON (GoldenVsToJSON (..)) +-- import Test.Tasty.Golden.Extra.GoldenVsToJSON (goldenVsToJSON) -- -- test_ToJSON :: TestTree -- test_ToJSON = do @@ -96,7 +58,7 @@ goldenVsToJsonFile name ref new act = -- goldenVsToJSON -- "Test ToJSON instance for Person" -- (goldenFilesPath \ "Person.golden.json") --- (Aeson.decodeFileStrict' inputFile) +-- (Aeson.decodeFileStrict' @Person inputFile) -- @ goldenVsToJson :: forall a. @@ -114,7 +76,7 @@ goldenVsToJson name fp act = name (Aeson.decodeFileStrict fp >>= orFailTest ("Couldn't decode golden JSON file:" <> fp)) (Aeson.toJSON <$> act) - assertJsonEqual + (\a b -> pure . maybeDifference $ checkJsonDifference a b) (BL.writeFile fp . encodePretty) orFailTest :: String -> Maybe a -> IO a diff --git a/src/Test/Tasty/Golden/Extra/GoldenVsToYAML.hs b/src/Test/Tasty/Golden/Extra/GoldenVsToYAML.hs index 9d7476f..4977140 100644 --- a/src/Test/Tasty/Golden/Extra/GoldenVsToYAML.hs +++ b/src/Test/Tasty/Golden/Extra/GoldenVsToYAML.hs @@ -16,7 +16,6 @@ -- that you want to convert to YAML using the @Data.Yaml@ package. module Test.Tasty.Golden.Extra.GoldenVsToYAML ( goldenVsToYaml, - goldenVsToYamlFile, GoldenVsToYAML (..), ) where @@ -29,7 +28,7 @@ import Data.Yaml qualified as Yaml import Test.Tasty import Test.Tasty.Discover qualified as Discover import Test.Tasty.Golden.Advanced (goldenTest) -import Test.Tasty.Golden.Extra.Internal (assertJsonEqual) +import Test.Tasty.Golden.Extra.Internal (checkJsonDifference, maybeDifference) -- | Tasty-discoverable type for creating golden tests for @ToJSON@ instances, -- that you want to convert to YAML using the @Data.Yaml@ package. @@ -42,8 +41,8 @@ import Test.Tasty.Golden.Extra.Internal (assertJsonEqual) -- import System.FilePath ((\)) -- import Test.Tasty.Golden.Extra.GoldenVsToYAML (GoldenVsToYAML (..)) -- --- tasty_FromJSON_ToJSON :: GoldenVsToYAML --- tasty_FromJSON_ToJSON = +-- tasty_FromJSON_ToYAML :: GoldenVsToYAML +-- tasty_FromJSON_ToYAML = -- GoldenVsToYAML (goldenFilesPath \ "Person.golden.yaml") $ -- Aeson.eitherDecodeFileStrict @Person (goldenFilesPath \ "Person.json") -- @ @@ -52,43 +51,6 @@ data GoldenVsToYAML = forall a. (Aeson.ToJSON a) => GoldenVsToYAML FilePath (IO instance Discover.Tasty GoldenVsToYAML where tasty info (GoldenVsToYAML ref act) = pure $ goldenVsToYaml (Discover.nameOf info) ref act --- | Helper function for creating a @TestTree@ for @ToJSON@-to-YAML golden tests. --- Use when you want to test code that produces a YAML file as a side effect. --- --- Example use: --- --- @ --- import MySchemasWithToJSONInstances.Person (Person, gen) --- import Data.Aeson qualified as Aeson --- import System.FilePath ((\)) --- import Test.Tasty.Golden.Extra.GoldenVsToYAML (GoldenVsToYAML (..)) --- --- test_ToYAML :: TestTree --- test_ToYAML = do --- person <- gen --- let outputFile = goldenFilesPath \ "Person.yaml" --- goldenVsToYamlFile --- "Test YAML serialization for Person" --- (goldenFilesPath \ "Person.golden.yaml") --- outputFile --- (Aeson.encodeFile outputFile person) --- @ -goldenVsToYamlFile :: - -- | test name - TestName -> - -- | path to the «golden» file (the file that contains correct output) - FilePath -> - -- | path to the output file - FilePath -> - -- | action that creates the output file - IO () -> - TestTree -goldenVsToYamlFile name ref new act = - goldenVsToYaml @Aeson.Value name ref $ do - act - eJson <- Yaml.decodeFileEither new - orFailTest new eJson - -- | Helper function for creating a @TestTree@ for @ToJSON@-to-YAML golden tests. -- Use when you want to test @ToJSON@ instances against a golden example of YAML -- on disk. @@ -99,7 +61,7 @@ goldenVsToYamlFile name ref new act = -- import MySchemasWithToJSONInstances.Person (Person) -- import Data.Aeson qualified as Aeson -- import System.FilePath ((\)) --- import Test.Tasty.Golden.Extra.GoldenVsToYAML (GoldenVsToYAML (..)) +-- import Test.Tasty.Golden.Extra.GoldenVsToYAML (goldenVsToYAML) -- -- test_ToYAML :: TestTree -- test_ToYAML = do @@ -107,7 +69,7 @@ goldenVsToYamlFile name ref new act = -- goldenVsToYAML -- "Test YAML serialization for Person" -- (goldenFilesPath \ "Person.golden.yaml") --- (Aeson.decodeFileStrict' inputFile) +-- (Aeson.decodeFileStrict' @Person inputFile) -- @ goldenVsToYaml :: forall a. @@ -125,7 +87,7 @@ goldenVsToYaml name fp act = name (Yaml.decodeFileEither fp >>= orFailTest fp) (Aeson.toJSON <$> act) - assertJsonEqual + (\a b -> pure . maybeDifference $ checkJsonDifference a b) (BL.writeFile fp . Yaml.encode) orFailTest :: FilePath -> Either Yaml.ParseException a -> IO a diff --git a/src/Test/Tasty/Golden/Extra/Internal.hs b/src/Test/Tasty/Golden/Extra/Internal.hs index 9e17d09..d1fbc80 100644 --- a/src/Test/Tasty/Golden/Extra/Internal.hs +++ b/src/Test/Tasty/Golden/Extra/Internal.hs @@ -1,5 +1,16 @@ +-- | +-- +-- Module : Test.Tasty.Golden.Extra.Internal +-- Copyright : (C) 2024 Bellroy Pty Ltd +-- License : BSD-3-Clause +-- Maintainer : Bellroy Tech Team +-- Stability : experimental +-- +-- Common types and functions used by the other modules in `tasty-golden-extra`. module Test.Tasty.Golden.Extra.Internal - ( assertJsonEqual, + ( checkJsonDifference, + maybeDifference, + JsonDifference (..), ) where @@ -9,8 +20,26 @@ import Data.Aeson.Patch (patchOperations) import Data.Text.Lazy qualified as TL import Text.Pretty.Simple (pShowNoColor) -assertJsonEqual :: Aeson.Value -> Aeson.Value -> IO (Maybe String) -assertJsonEqual goldenJson actualJson = - pure $ case patchOperations $ diff goldenJson actualJson of - [] -> Nothing - ds -> Just $ "Files contain different JSON values: " <> TL.unpack (pShowNoColor ds) +-- | Represents the result of comparing two JSON values - either the JSON is +-- identical, or there are differences and you are given an error message +-- containing the differences. +data JsonDifference + = JsonIdentical + | JsonDifferent String + +-- | Convert a `JsonDifference` to a `Maybe String` containing the error message. +maybeDifference :: JsonDifference -> Maybe String +maybeDifference JsonIdentical = Nothing +maybeDifference (JsonDifferent diffString) = Just diffString + +-- | Compare two JSON values and return a `JsonDifference` representing the result. +checkJsonDifference :: + Aeson.Value -> + Aeson.Value -> + JsonDifference +checkJsonDifference goldenJson actualJson = + case patchOperations $ diff goldenJson actualJson of + [] -> JsonIdentical + ds -> + JsonDifferent $ + "Files contain different JSON values:\n" <> TL.unpack (pShowNoColor ds) diff --git a/tasty-golden-extra.cabal b/tasty-golden-extra.cabal index be23416..20e516e 100644 --- a/tasty-golden-extra.cabal +++ b/tasty-golden-extra.cabal @@ -63,11 +63,10 @@ library ghc-options: -Wunused-packages hs-source-dirs: src - -- cabal-fmt: expand src/ -Test.Tasty.Golden.Extra.Internal + -- cabal-fmt: expand src/ exposed-modules: Test.Tasty.Golden.Extra.GoldenVsShow Test.Tasty.Golden.Extra.GoldenVsString Test.Tasty.Golden.Extra.GoldenVsToJSON Test.Tasty.Golden.Extra.GoldenVsToYAML - - other-modules: Test.Tasty.Golden.Extra.Internal + Test.Tasty.Golden.Extra.Internal