Reputation: 354
I'd like to write unit tests for abstract syntax trees generated by a parser that I write using FParsec.
For instance, given the parser
open FParsec
type FooValue = FooValue of int
let foo: Parser<string,unit> = pstring "foo"
let fooValue = pint32
let p = foo >>. spaces >>. fooValue |>> FooValue.FooValue
the only testing way I found so far was writing
let resultSuccess = run p "foo 23"
let resultFailure = run p "foo noNumber"
printfn "%O" resultSuccess
printfn "%O" resultFailure
and checking if my F# program outputs
Success: FooValue 23
Failure:
Error in Ln: 1 Col: 5
foo noNumber
^
Expecting: integer number (32-bit, signed)
Instead, I'd prefer to write some unit tests like these:
open FParsec
open Microsoft.VisualStudio.TestTools.UnitTesting
[<TestClass>]
type TestMyParser () =
[<TestMethod>]
member this.TestPSucceeds () =
let actual = run p "foo 23"
let expected = ......?
Assert.AreEqual(actual, expected);
[<TestMethod>]
member this.TestPFails () =
let actual = run p "foo noNumber"
let expected = ......?
Assert.AreEqual(actual, expected);
As you can see, I have no clue how to construct valid functions for expected values of the abstract syntax trees of FParsec so I could somehow compare them with the actual result of each test I run.
Edit: It would help me also (and probably simplify the comparison of more complex ASTs a lot) if I could somehow serialize the actual results to strings and just compare them to expected strings.
Upvotes: 1
Views: 34
Reputation: 354
I found out how to do it, it is relatively simple using sprintf
. The TestMethod could look like this:
[<TestMethod>]
member this.TestPSucceeds () =
let result = run p "foo 23"
let actual = sprintf "%O" result
let expected = """Success: FooValue 23""".Replace("\r","")
Assert.AreEqual(expected, actual);
Enclosing the expected string in """
, followed by the Replace("\r","")
function makes sure that you can also paste more complex, multi-line parser output here.
Upvotes: 0