Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show less context on failure #505

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 72 additions & 11 deletions hedgehog/src/Hedgehog/Internal/Report.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ module Hedgehog.Internal.Report (
, Style(..)
, Markup(..)

, Context(..)
, Lines

, renderProgress
, renderResult
, renderResultWith
, renderSummary
, renderDoc

, ppProgress
, ppResult
, ppResultWith
, ppSummary

, fromResult
Expand Down Expand Up @@ -181,7 +186,7 @@ summaryTotal (Summary x1 x2 x3 x4 x5) =

data Line a =
Line {
_lineAnnotation :: !a
lineAnnotation :: !a
, lineNumber :: !LineNo
, _lineSource :: !String
} deriving (Eq, Ord, Show, Functor)
Expand Down Expand Up @@ -553,9 +558,46 @@ ppFailureLocation msgs mdiff sloc =
pure $
mapSource (styleFailure . insertDoc) decl

type Annotation = (Style, [(Style, Doc Markup)])

newtype Lines = Lines Int
deriving (Eq, Num)

instance Show Lines where
showsPrec p (Lines n) = showsPrec p n

data Context = FullContext | Context Lines

applyContext :: Context -> Declaration Annotation -> Declaration Annotation
applyContext context decl = case context of
FullContext -> decl
Context n -> decl { declarationSource = limitContextTo n (declarationSource decl) }

limitContextTo :: Lines -> Map LineNo (Line Annotation) -> Map LineNo (Line Annotation)
limitContextTo (Lines context) =
let
skipBoring xs = case span isBoring xs of
(boring, []) -> take context boring
(boring, rest) -> takeEnd context boring <> keepInteresting rest

keepInteresting xs = case break isBoring xs of
(interesting, rest) -> interesting <> take context rest <> skipBoring rest

isBoring = isBoringAnnotation . lineAnnotation . snd
in
Map.fromList . skipBoring . Map.toList

takeEnd :: Int -> [a] -> [a]
takeEnd n = reverse . take n . reverse

isBoringAnnotation :: Annotation -> Bool
isBoringAnnotation = \ case
(StyleDefault, []) -> True
_ -> False

ppDeclaration :: Declaration (Style, [(Style, Doc Markup)]) -> Doc Markup
ppDeclaration decl =
case Map.maxView $ declarationSource decl of
ppDeclaration decl = let source = declarationSource decl in
case Map.maxView source of
Nothing ->
mempty
Just (lastLine, _) ->
Expand All @@ -578,17 +620,30 @@ ppDeclaration decl =

ppSource :: Style -> LineNo -> String -> Doc Markup
ppSource style n src =
(if isOmittedLine (pred n) then addVerticalEllipsis else id) $
markup (StyledLineNo style) (ppLineNo n) <+>
markup (StyledBorder style) "┃" <+>
markup (StyledSource style) (WL.text src)

addVerticalEllipsis =
(verticalEllipsis <#>)

verticalEllipsis =
"\x22ee"

isOmittedLine n =
n >= firstLine && Map.notMember n source

firstLine =
fst $ Map.findMin source

ppAnnot (style, doc) =
markup (StyledLineNo style) ppEmptyNo <+>
markup (StyledBorder style) "┃" <+>
doc

ppLines = do
Line (style, xs) n src <- Map.elems $ declarationSource decl
Line (style, xs) n src <- Map.elems source
ppSource style n src : fmap ppAnnot xs
in
WL.vsep (ppLocation : ppLines)
Expand Down Expand Up @@ -624,8 +679,8 @@ ppTextLines :: String -> [Doc Markup]
ppTextLines =
fmap WL.text . List.lines

ppFailureReport :: MonadIO m => Maybe PropertyName -> TestCount -> DiscardCount -> Seed -> FailureReport -> m [Doc Markup]
ppFailureReport name tests discards seed (FailureReport _ shrinkPath mcoverage inputs0 mlocation0 msg mdiff msgs0) = do
ppFailureReport :: MonadIO m => Context -> Maybe PropertyName -> TestCount -> DiscardCount -> Seed -> FailureReport -> m [Doc Markup]
ppFailureReport context name tests discards seed (FailureReport _ shrinkPath mcoverage inputs0 mlocation0 msg mdiff msgs0) = do
let
basic =
-- Move the failure message to the end section if we have
Expand Down Expand Up @@ -713,7 +768,7 @@ ppFailureReport name tests discards seed (FailureReport _ shrinkPath mcoverage i
with args $
WL.punctuate WL.line
, with decls $
WL.punctuate WL.line . fmap ppDeclaration
WL.punctuate WL.line . fmap (ppDeclaration . applyContext context)
, with msgs1 $
id
, with bottom $
Expand Down Expand Up @@ -751,10 +806,13 @@ ppProgress name (Report tests discards coverage _ status) =
"(shrinking)"

ppResult :: MonadIO m => Maybe PropertyName -> Report Result -> m (Doc Markup)
ppResult name (Report tests discards coverage seed result) = do
ppResult = ppResultWith FullContext

ppResultWith :: MonadIO m => Context -> Maybe PropertyName -> Report Result -> m (Doc Markup)
ppResultWith context name (Report tests discards coverage seed result) = do
case result of
Failed failure -> do
pfailure <- ppFailureReport name tests discards seed failure
pfailure <- ppFailureReport context name tests discards seed failure
pure . WL.vsep $ [
icon FailedIcon '✗' . WL.align . WL.annotate FailedText $
ppName name <+>
Expand Down Expand Up @@ -1226,8 +1284,11 @@ renderProgress color name x =
renderDoc color =<< ppProgress name x

renderResult :: MonadIO m => UseColor -> Maybe PropertyName -> Report Result -> m String
renderResult color name x =
renderDoc color =<< ppResult name x
renderResult = renderResultWith FullContext

renderResultWith :: MonadIO m => Context -> UseColor -> Maybe PropertyName -> Report Result -> m String
renderResultWith context color name x =
renderDoc color =<< ppResultWith context name x

renderSummary :: MonadIO m => UseColor -> Summary -> m String
renderSummary color x =
Expand Down
Loading