Search code examples
prologdiffswi-prologedit-distanceplunit

How can I improve error reporting using PlUnit?


I'm writing tests using SWI-Prolog's PlUnit and would like to provide a better error message, perhaps by diffing what I've got from what I was expecting.

The following minimal working example (MWE) exemplifies what I'm after:

:- module(mwe, [parse_int/2]).

parse_int(Str, Num) :- number_string(Num, Str):

:- begin_tests(mwe).
:- use_module(mwe).

testcase("1", 1).
testcase("10", 10).
testcase("100000000000", 10000000000). % Oops
test("parse int", [forall(testcase(Text, Want))]) :-
  parse_int(Text, Got),
  assertion(Got = Want).

:- end_tests(mwe).

The output is:

% PL-Unit: mwe ..
ERROR: /home/bkim/Projects/swifun/mwe.pl:11:
    test parse int (forall bindings = ["100000000000",10000000000]): assertion failed
    Assertion: 100000000000=10000000000
false.

A differ, similar to go-cmp, could present this result like:

- 100000000000
+ 10000000000

Which is easier to compare at a glance.

I couldn't find anything that performs this type of check for general Prolog terms, the closer being an example of edit distance between lists.


Solution

  • You should move the comparison into the test rule's head:

    test("parse int", [forall(testcase(Text, Want)), Got = Want]) :-
        parse_int(Text, Got).
    

    This way it's more explicit what you want the test to express. And it allows PlUnit to give more informative output:

    ERROR: /home/isabelle/foo.pl:11:
        test parse int (forall bindings = ["100000000000",10000000000]): wrong answer (compared using =)
    ERROR:     Expected: 10000000000
    ERROR:     Got:      100000000000