How do I improve QuickCheck and Parsec debugging?
Asked Answered
S

1

7

I am using Haskell and Parsec to parse a file format. My parsing function looks something like:

parseInput :: String -> Model
parseInput input = ...

data Model = Model { mNumV :: Int, mNumF :: Int, ... }

In order to test this, I am using QuickCheck. I have defined an Arbitrary instance that generates a String representing the contents of a formatted file:

instance Arbitrary File where
    arbitrary = ...

data File = File { fContents :: String, fNumV :: Int, fNumF :: Int, ... }

One of my properties might check to determine if mNumV == fNumV after parsing the arbitrary String. This works well - when it works.

But if something fails, Parsec throws an error similar to:

*** Failed (after 1 test):
Exception:
  (line 302, column 3):
  unexpected "\n"
  expecting space

This is useful - however, after the test fails the contents of the arbitrary file disappear. I can't go in and reference line 302.

The only alternative that I can see is to print the fContents of each arbitrary file after each test - but that seems like a terrible idea. The same goes for routing every arbitrary file to a file on disk for later reference.

Is there a common way around this?

Specht answered 16/1, 2014 at 7:40 Comment(5)
There is another question about how to return the value that quickCheck failed for: #8191631Papua
@JakobRunge I think I already have that value - I'm missing some way to get the line number from Parsec and do a look up on the file contents.Specht
If you know how to get the failing value, and Parsec has given you the line and column number, shouldn't you be able to go to that location to see which input is giving the error?Cashmere
hackage.haskell.org/package/parsec-3.1.5/docs/… returns Either ParseError a and you can get the sourcepos from Left errTeepee
@Teepee I think that's what I want, thanks - I am going to try it out in a bit. If you want to post an answer, I will accept that as it seems like a good solution.Specht
B
1

You can use whenFail to print the offending string (or dump it to a file) upon failure.

Barny answered 16/1, 2014 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.