-
Notifications
You must be signed in to change notification settings - Fork 11
Open
Labels
Description
To demonstrate the problem, let's intentionally introduce a bug:
diff --git a/src/TextShow/Data/Functor/Identity.hs b/src/TextShow/Data/Functor/Identity.hs
index 1c69008..b10bc81 100644
--- a/src/TextShow/Data/Functor/Identity.hs
+++ b/src/TextShow/Data/Functor/Identity.hs
@@ -27,5 +27,5 @@ instance TextShow a => TextShow (Identity a) where
instance TextShow1 Identity where
-- This would be equivalent to the derived instance of 'Identity' if the
-- 'runIdentity' field were removed.
- liftShowbPrec sp _ p (Identity x) = showbUnaryWith sp "Identity" p x
+ liftShowbPrec sp _ p (Identity x) = showbUnaryWith sp "Jdentity" p x
{-# INLINE liftShowbPrec #-}If we run the test suite, we see the following failure:
$ cabal test
<snip>
Failures:
tests/Spec/Utils.hs:73:44:
1) Spec.Data.Functor.Identity, Identity Int, TextShow1 instance
Falsifiable (after 1 test):
0
Identity 0
expected: "Identity 0"
but got: "Jdentity 0"
To rerun use: --match "/Spec.Data.Functor.Identity/Identity Int/TextShow1 instance/" --seed 964037888
Randomized with seed 964037888
Finished in 0.1559 seconds
403 examples, 1 failure
Test suite spec: FAIL
<snip>
This claims that the failure arises from tests/Spec/Utils.hs:73:44:, but the relevant test case is actually defined in tests/Spec/Data/Functor/IdentitySpec.hs. The problem is that we define our own hspec combinators in tests/Spec/Utils.hs, such as this one from line 73:
Lines 72 to 73 in 3f362a3
| prop_matchesTextShow1 :: (Show1 f, Show a, TextShow1 f, TextShow a) => Int -> f a -> Expectation | |
| prop_matchesTextShow1 p x = showbPrec1 p x `shouldBe` fromString (showsPrec1 p x "") |
In order to make this report the correct source location, we need to give this (and similar functions) as HasCallStack constraint, e.g.,
diff --git a/tests/Spec/Utils.hs b/tests/Spec/Utils.hs
index 7938ebe..0d2e59b 100644
--- a/tests/Spec/Utils.hs
+++ b/tests/Spec/Utils.hs
@@ -35,6 +35,7 @@ import Data.Functor.Classes (Show1, Show2, showsPrec1, showsPrec2)
import Data.Proxy (Proxy(..))
import GHC.Generics
+import GHC.Stack (HasCallStack)
import Test.Hspec (Expectation, Spec, shouldBe)
import Test.Hspec.QuickCheck (prop)
@@ -69,7 +70,7 @@ matchesTextShow1Spec _ = prop "TextShow1 instance" (prop_matchesTextShow1 :: Int
-- | Verifies that a type's 'Show1' instances coincide for both 'String's and 'Text',
-- irrespective of precedence.
-prop_matchesTextShow1 :: (Show1 f, Show a, TextShow1 f, TextShow a) => Int -> f a -> Expectation
+prop_matchesTextShow1 :: (HasCallStack, Show1 f, Show a, TextShow1 f, TextShow a) => Int -> f a -> Expectation
prop_matchesTextShow1 p x = showbPrec1 p x `shouldBe` fromString (showsPrec1 p x "")
-- | Expect a type's 'Show2' instances to coincide for both 'String's and 'Text',Then the test suite would report the location of the failing test correctly:
$ cabal test
<snip>
Failures:
tests/Spec/Utils.hs:69:53:
1) Spec.Data.Functor.Identity, Identity Int, TextShow1 instance
Falsifiable (after 1 test):
0
Identity 0
expected: "Identity 0"
but got: "Jdentity 0"
To rerun use: --match "/Spec.Data.Functor.Identity/Identity Int/TextShow1 instance/" --seed 29982196
Randomized with seed 29982196
Finished in 0.1483 seconds
403 examples, 1 failure
Test suite spec: FAIL
<snip>