-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathGolden.hs
80 lines (73 loc) · 2.76 KB
/
Golden.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
{-# LANGUAGE ScopedTypeVariables #-}
-- | "Golden tests" using 'ediff' comparison.
module Data.TreeDiff.Golden (
ediffGolden,
ediffGolden1,
) where
import Data.TreeDiff
import System.Console.ANSI (SGR (Reset), setSGRCode)
import Text.Parsec (eof, parse)
import Text.Parsec.Text ()
import qualified Data.ByteString as BS
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Text.PrettyPrint.ANSI.Leijen as WL
-- | Make a golden tests.
--
-- 'ediffGolden' is testing framework agnostic, thus the type
-- looks intimidating.
--
-- An example using @tasty-golden@,
-- 'goldenTest' is imported from "Test.Tasty.Golden.Advanced"
--
-- @
-- exTest :: TestTree
-- exTest = 'ediffGolden' goldenTest "golden test" "fixtures/ex.expr" $
-- action constructing actual value
-- @
--
-- The 'ediffGolden' will read an 'Expr' from provided path to golden file,
-- and compare it with a 'toExpr' of a result. If values differ,
-- the (compact) diff of two will be printed.
--
-- See <https://github.com/phadej/tree-diff/blob/master/tests/Tests.hs>
-- for a proper example.
--
ediffGolden
:: ToExpr a
=> (testName -> IO Expr -> IO Expr -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -- ^ 'goldenTest'
-> testName -- ^ test name
-> FilePath -- ^ path to "golden file"
-> IO a -- ^ result value
-> testTree
ediffGolden impl testName fp x = ediffGolden1 impl' testName fp (\() -> x) where
impl' n expect actual = impl n expect (actual ())
-- | Like 'ediffGolden1' but with an additional argument for generation of actual value.
--
-- @since 0.3.2
--
ediffGolden1
:: forall a arg testName testTree. ToExpr a
=> (testName -> IO Expr -> (arg -> IO Expr) -> (Expr -> Expr -> IO (Maybe String)) -> (Expr -> IO ()) -> testTree) -- ^ 'goldenTest'
-> testName -- ^ test name
-> FilePath -- ^ path to "golden file"
-> (arg -> IO a) -- ^ result value
-> testTree
ediffGolden1 impl testName fp x = impl testName expect actual cmp wrt
where
actual :: arg -> IO Expr
actual arg = fmap toExpr (x arg)
expect :: IO Expr
expect = do
contents <- BS.readFile fp
case parse (exprParser <* eof) fp $ TE.decodeUtf8 contents of
Left err -> return $ App "ParseError" [toExpr fp, toExpr (show err)]
Right r -> return r
cmp :: Expr -> Expr -> IO (Maybe [Char])
cmp a b
| a == b = return Nothing
| otherwise = return $ Just $
setSGRCode [Reset] ++ showWL (ansiWlEditExprCompact $ ediff a b)
wrt expr = BS.writeFile fp $ TE.encodeUtf8 $ T.pack $ showWL (WL.plain (ansiWlExpr expr)) ++ "\n"
showWL :: WL.Doc -> String
showWL doc = WL.displayS (WL.renderSmart 0.4 80 doc) ""