plunit and forall(:Generator)

Skip to first unread message

Sean Charles

Mar 14, 2018, 11:01:19 AM3/14/18
to SWI-Prolog
Utterly stumped.

I have been writing unit tests for my code and I want to refactor them so that the common ones that have a string as input and a known list of tokens to check against can be run as one test... but I cannot figure it out!

I have searched the forums for "plunit" and "generator" and "forall" but nothing turned up.

How does one do it?

The documentation says "Run the same test for each solution of Generator." ...but that's it! I can't even begin to think how you would pass the output of the generator into the test body?!?!?!

Just one single clear cut example would be amazing.

I am reading the source code to try to figure it out, at least I am still learning!!


Boris Vassilev

Mar 14, 2018, 11:20:06 AM3/14/18
to Sean Charles, SWI-Prolog
Hello Sean,

this is how _in my understanding_ forall is meant to be used in PlUnit:

$ cat
:- module(foo, [triple/2]).

:- begin_tests(foo).

test_triple(x, xxx).
test_triple(3, 333).
test_triple(foo, foofoofoo).

test(triple_atom, [forall(test_triple(X, Y))]) :-
    triple(X, Y).

:- end_tests(foo).

triple(X, Y) :-
    atomic_list_concat([X, X, X], Y).
$ swipl -g 'use_module(foo), run_tests' -g halt
% PL-Unit: foo .
ERROR: /home/boris/code/prolog/
    test triple_atom (forall bindings = [3,333]): failed

. done
% 1 test failed
% 2 tests passed
ERROR: -g use_module(foo), run_tests: false

This is of course a simplified example, but it shows that you get to see which case failed (if you inline the three cases inside one test, and one fails, you don't know which one).

Does that answer your question?


Save our in-boxes!

You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
Visit this group at
For more options, visit

Sean Charles

Mar 14, 2018, 11:39:13 AM3/14/18
to SWI-Prolog
I now have this:

test('whitespace in parens test',
     [forall(testdata_whitespace_between_parens(In, Out))]):-
feltparser:parse(string(In), Out).

testdata_whitespace_between_parens(`()`, [nil(pos(0))]).
testdata_whitespace_between_parens(` (   )`, [nil(pos(1))]).
testdata_whitespace_between_parens(`\n\n(\r\n    \r\r\r\n)`, [nil(pos(2))]).

And from that I have learned an awful lot and I am now busy refactoring everything that needs refactoring into smaller code.

Thanks for you time, very much appreciated!
All the best,
To unsubscribe from this group and stop receiving emails from it, send an email to
Reply all
Reply to author
0 new messages