Setting Up Unit Testing In SWI-Prolog

Reading the docs for plunit, it can be quite tricky to figure out how to setup a unit testing environment and actually run those tests. In this post we look at how to do it, keeping tests separate from code, and running them with a handy command.


BEFORE TESTING, let’s structure our project. For this example we’ll diagnose an apple to see if it is good to eat. First we’ll setup our file structure, then we’ll add the content, and run the tests.

Get Organised

A STANDARD structure is to separate your knowledge base from your reasoning over it. This makes it easier to interchange your knowledge base. We’ll also keep our tests in their own file for the sake of readability.

Setup the following file structure, you can download the files to follow along:

project/
|-- kb.pl
(PLUnit Example Knowledge Base)
|-- inference.pl (PLUnit Example Inference Predicates)
|-- inference.plt (PLUnit Example Inference Tests)

kb.pl holds the facts, data, knowledge, whatever you wish to call it. There’s no reasoning done in that file. inference.pl is our placeholder name for where you do your fancy work, reasoning, etc. inference.plt is the test file, it must have the same name as what you’re testing for SWI-Prolog to automatically find it and load it. The only difference is the “t” on the end.

Let's look at the Prolog.

Starting with kb.pl, there’s some rather glib information about apples. ako stands for “a kind of”, isa is the “is a” relationship, i.e. an instance of some class. We have some information on what an apple is, and a few different kinds of apples. We then have three instances of those apples, boringly called test_subjectN. To make thing’s fun, we also have a maggot called Maud, who’s living in one of the apples.

Then there's inference.pl, this defines ako as a transitive relationship and makes isa smart too. From there I’ve just created some quick conditions to determine if an apple is edible. This is the file you’d run and query, the unit tests for it are in inference.plt.

Running The Tests

There are two ways to run them, from the swipl prompt, or command line. When running from the swipl prompt, if you’re still adding tests, include make(all) in the options so when you query make. it also makes your tests. If you’ve done with that you can omit it: load_test_files([]).

bash:~/ $ swipl inference.pl
Welcome to SWI-Prolog <etc...>
?- load_test_files([make(all)]).
true.
?- run_tests.

From the command line you can call:

swipl -t "load_test_files([]), run_tests." -s inference.pl

This tell’s swipl to load the source file inference.pl and to run the tests as a top goal. I like to set an alias for easy testing, you can add the following to the end of your .bashrc, or set it locally, assuming you’re a fellow bash user.

alias plunit='swipl -t "load_test_files([]), run_tests." -s'

Now you can run the tests by simply typing:

plunit inference.pl

Conclusion

We've got unit tests in their own file, working with separate knowledge base and reasoning. Plus, we can run them very easily. I’ve not gone into detail about how to write unit tests or how to use plunit. The docs are actually not too difficult to follow once you’ve seen an example and got a setup running. Hopefully, this has been helpful enough to get you started!