Prosaic Prolog: Unit testing with SWI Prolog
I’ve been trying to learn Prolog, since it seems to be built out of a very different and beautiful set of paradigms than any other programming language I’ve used.
One of my frustrations has been that doing straightforward things seems to be either poorly documented or confusing because of the paradigm shift required by writing logic programs.
To that end, I’m recording simple “prosaic” tasks in “Prosaic Prolog” posts.
The goal here is the following: set up a directory structure and list of files so that I can run tests from the command line and have it tell me if there’s a bug.
Buggy code
To start out, let’s write a buggy predicate add/3
, which is just like arithmetic addition, except it thinks that 2+2 is 5. Here are the contents of bug.pl
:
This predicate is defined by two rules. The first says “2 plus 2 is 5 and you can stop trying other things now.” The “stop trying” is set by the cut operation !
. The second says “add/3
behaves like regular addition” except in the first case.
You can see that this is buggy by running it in swi-prolog REPL:
plunit
Now let’s write a unit test using plunit
, adding them to the bottom of the bug.pl
file
You can verify that these tests fail in the repl:
Running from the command line
swipl -t '[bug], run_tests.'
The -t
option allows you to specify a goal that the engine should solve. In this case, we gave it the goal of loading the bug
file and solving the run_tests
goal:
Importantly for integration with CI systems, the command has a nonzero exit status:
With the -g
option, you can give it a trivial goal to execute instead of the default welcome message predicate, so the cleaned up output is:
Open Question
How do you get plunit to run in a separate bug.plt file, so that tests aren’t intermingled with code?
Thanks to Stackoverflow user Steven for helping with this post in his answer to this question.