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

Include file/line/column of failed assertion in output? #306

Closed
owickstrom opened this issue Jun 20, 2019 · 9 comments · Fixed by #308
Closed

Include file/line/column of failed assertion in output? #306

owickstrom opened this issue Jun 20, 2019 · 9 comments · Fixed by #308

Comments

@owickstrom
Copy link
Contributor

Hi! This is going to sound like a very Emacs-specific problem, but please bear with me. 🙂

I'm using Hedgehog a lot through Emacs' compilation-mode (or the haskell-compilation buffer, to be specific). I was trying to add a pattern to haskell-compilation-error-regexp-alist, which would let me navigate between failed tests using the regular "previous/next error" functions in Emacs.

The problem is that Hedgehog's output is awesome for human consumption, but not so much for Emacs consumption as it doesn't support multi-line error matchers. Even if it did, I couldn't come up with a reliable way of parsing file, line, and column information.

Would it make sense to add, somewhere in the output of a failing test, a line like:

Test failed at: my/path/to/FailedTest.hs:54:4

Or, in case the test threw some exception:

Test errored at: my/path/to/FailedTest.hs:54:4

That would be much more tractable to parse in Emacs (and I guess in other editors, recalling my fun days with Vim's errorformat).

Outstanding questions that I can come up with:

  • Where in the existing output, if anywhere, could this be placed?
  • Do we have column information? If not, just having the line number is still good, so that you can navigate to the failing assertion's line.
  • Should this be hidden by a flag/environment variable? Maybe it clutters the existing nice output.

I'd be happy to put together a PR after we've discussed options.

Thanks!

@jacobstanley
Copy link
Member

jacobstanley commented Jun 20, 2019

I believe if you search for Span in https://github.com/hedgehogqa/haskell-hedgehog/blob/master/hedgehog/src/Hedgehog/Internal/Report.hs you should find the info you're looking for, it does indeed have the column as we need it to render the ^^^^^ arrows

Haha with a complex enough multiline regex I think we could do what you want already (looking for the arrows) but perhaps we could make that a little easier.

I could imagine we might be able to put it in the header line e.g:

        ┏━━ my/path/to/FailedTest.hs:54:4 ━━━

Not sure if that's better or not than a separate printout.

@owickstrom
Copy link
Contributor Author

That would absolutely work! As long as it's fine that 54:4 in this case is not necessarily the first actual line number in the code listing, but the line where the assertion failed/threw?

@jacobstanley
Copy link
Member

yeah both sets of information should be available, so would be up to you to pick the right one, I'm happy for it to be where the error occurred

@jacobstanley
Copy link
Member

jacobstanley commented Jun 20, 2019

there is also the possibility that there are other code blocks / functions are printed, like if you annotate in one function and the error occurs in another.

for those auxiliary code blocks I would expect they wouldn't have the line:col suffix

@owickstrom
Copy link
Contributor Author

Yeah, that sort of suggests that the line/column printout should be separate. I'm a bit weary about conflating the pretty code listings with this information.

@jacobstanley
Copy link
Member

Yeah so I trust you'll preserve the aesthetics as best you can! I'm happy for you to experiment and come up with something you think looks nice.

@owickstrom
Copy link
Contributor Author

owickstrom commented Jun 20, 2019

Something like this could work, after the failed after 4 tests and 1 shrink line (example from https://teh.id.au/posts/2017/07/15/state-machine-testing/):

*Test.Example.Turnstile> check prop_turnstile
  ✗ <interactive> failed after 4 tests and 1 shrink,
    at test/Test/Example/Turnstile.hs:153:7.

        ┏━━ test/Test/Example/Turnstile.hs ━━━
    130 ┃ s_push_unlocked :: (Monad n, MonadIO m, MonadTest m) => Turnstile -> Command n m ModelState
          <snip>
    150 ┃         -- Postcondition: we gain admission, the turnstile gate is locked.
    151 ┃       , Ensure $ \before after Push b -> do
    152 ┃           before === TUnlocked
    153 ┃           assert b
        ┃           ^^^^^^^^

        ┏━━ test/Test/Example/Turnstile.hs ━━━
    159 ┃ prop_turnstile :: Property
    160 ┃ prop_turnstile =
    161 ┃   property $ do
    162 ┃     turnstile <- liftIO newTurnstile
    163 ┃     actions <- forAll $
    164 ┃       Gen.actions (Range.linear 1 100) initialState [
    165 ┃           s_coin turnstile
    166 ┃         , s_push_locked turnstile
    167 ┃         , s_push_unlocked turnstile
    168 ┃         ]
        ┃         │ [ Var 0 :<- Push ]
    169 ┃     executeSequential initialState actions

    This failure can be reproduced by running:
    > recheck (Size 3) (Seed 8794484450743003252 4983793967879311195) <property>

with the at ... always being on a separate line.

@jacobstanley
Copy link
Member

Yeah that's nice, I would try some variations too and see how they look:

*Test.Example.Turnstile> check prop_turnstile
  ✗ <interactive> failed after 4 tests and 1 shrink,
    at test/Test/Example/Turnstile.hs:153:7
*Test.Example.Turnstile> check prop_turnstile
  ✗ <interactive> failed after 4 tests and 1 shrink.
    test/Test/Example/Turnstile.hs:153:7
*Test.Example.Turnstile> check prop_turnstile
  ✗ <interactive> failed at test/Test/Example/Turnstile.hs:153:7 after 4 tests and 1 shrink.
*Test.Example.Turnstile> check prop_turnstile
  ✗ <interactive> failed at test/Test/Example/Turnstile.hs:153:7
    after 4 tests and 1 shrink.

@owickstrom
Copy link
Contributor Author

I think I like number 4 the most.

owickstrom added a commit to owickstrom/haskell-hedgehog that referenced this issue Jun 20, 2019
Fixes hedgehogqa#306.

Adds the location of the failed assertion (taken from the Span value
of the failure report). Example output:

```
 ✗ <interactive> failed at test/Test/Hedgehog/Applicative.hs:91:11
    after 1 test.

       ┏━━ test/Test/Hedgehog/Applicative.hs ━━━
    69 ┃ ...

```

This enables editors to easily parse the location of failed test
assertions and provide links/jump functionality.
jacobstanley pushed a commit that referenced this issue Jun 21, 2019
* Include location of failed assertion in report

Fixes #306.

Adds the location of the failed assertion (taken from the Span value
of the failure report). Example output:

```
 ✗ <interactive> failed at test/Test/Hedgehog/Applicative.hs:91:11
    after 1 test.

       ┏━━ test/Test/Hedgehog/Applicative.hs ━━━
    69 ┃ ...

```

This enables editors to easily parse the location of failed test
assertions and provide links/jump functionality.

* Match style guide
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants