A tool for running in-source unittests for Anwer Set Programming (ASP)
Project description
asp-selftest
Starting with in-source testing in mind, asp-selftest has evolved into:
- In-source test runner for Answer Set Programming (
ASP) with Clingo. - Rich
SyntaxErrors withASPsource, based on Clingo's log messages. - Minimalistic plugins based on
ASPpredicates used as directives. (plugins: reification, clingo_main, dynamic plugins, sequencing, testrunner, mimic default clingo)
In-source Testing
It allows one to write constraints in ASP that will automatically be checked on loading. Consider logic.lp which contains:
node(A) :- edge(A, _).
node(B) :- edge(_, B).
cannot("at least one edge") :- not { edge(_, _) } > 0.
#program test_edge_leads_to_nodes(base).
edge(x, y).
cannot("node x") :- not node(x).
cannot("node y") :- not node(y).
cannot("node z") :- not node(z). % fails
Using cannot we capture the results from constraints that cannot be true. This leads to the following output:
$ clingo+ logic.lp --run-tests
...
AssertionError: cannot("at least one edge")
File test.lp, line 1, in base().
Model:
<empty>
If we fix it (remove it), we get the next failure:
$ clingo+ logic.lp --run-tests
...
AssertionError: cannot("node z")
File test.lp, line 5, in test_edge_leads_to_nodes(base).
Model:
edge(x,y) node(x) node(y)
SyntaxError
If we make a mistake, it tells us in a sensible way:
$ clingo+ logic.lp
...
Traceback (most recent call last):
...
File "logic.lp", line 2
1 node(A) :- edge(A, _).
2 node(B) :- edge(_, A).
^ 'B' is unsafe
^^^^^^^^^^^^^^^^^^^^^^^^ unsafe variables in: node(B):-[#inc_base];edge(#Anon0,A).
Status
This tools is still a work in progress. I use it for a project to providing formal specifications for railway interlocking. It consist of 35 files, 100+ tests and 600+ cannots.
asp-selftest has been presented at Declarative Amsterdam in November 2024.
Changes
From version v0.0.30 upwards, @all, @any, @model and the special treatment of predicate assert are removed.
From this version on, only cannot is supported.
Tests from #include files are run in their own context, making it easier to add cannot to base-parts.
It is tenfold faster. It runs all my 100+ tests in less than 2 seconds.
Also, asp-test is removed. Only clingo+ remains. The latter is a drop-in replacement for clingo with the added ability to activate plugins, of which these are default:
TesterHook- runs in-source unit tests.SyntaxErrorHandler- provides nice in-source error messages, a la Python
You can write you own plugins. I have one for reifying rules from theory atoms, for example.
Why In-Source?
With in-source testing, source and tests stay together in the same file. This enables automatic collection and running and avoid maintaining a test tree, and it eases refactoring greatly.
Installing and running
Installing
pip install asp-selftest
Run it using:
$ clingo+ <file.lp> --run-tests
There is one additional option to silence the in-source Python tests:
$ clingo+ --silent --run-tests
A bit of documentation
-
Use
#program's to specify tests and their dependencies. Here we have a unit calledunit_Awith a unit test for it calledtest_unit_A. Test must start withtest_. Formal arguments are treated as dependencies.#program unit_A. #program test_unit_A(base, unit_A).The implicit program
base(see Clingo Guide) must be referenced explicitly if needed.The actual arguments to
test_unit_awill be a generic placeholder and have no meaning insidetest_unit_A. -
Within a test program, use
cannotmuch like ASP constraints, only with a head. Its arguments are just for identification in the reporting.#program step. fact. #program test_step(step). cannot("step fact") :- not fact(3).Note that
"step fact"is just a way of distinquishing the constraint. It can be an atom, a string, a number or anything else. -
Note that
cannotis much like an constraint inASP. To assertsomefactis true, we must usenot:somefact. cannot("somefact must be true") :- not somefact.It is helpful to read
cannotas it cannot be the case that.... Alternatively, one can useconstraintas an alias forcannot. Just your preference.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asp_selftest-0.0.31.tar.gz.
File metadata
- Download URL: asp_selftest-0.0.31.tar.gz
- Upload date:
- Size: 44.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
104401119c36e64a127b6721d529ce510a60a85b4182c8cf7bed0095774da675
|
|
| MD5 |
4a2b971ea6af235f7bec25e126055f12
|
|
| BLAKE2b-256 |
b71a5f35327118447897d8893a1d05f903324aeb69d99a2da92f6d91f5e37425
|
File details
Details for the file asp_selftest-0.0.31-py3-none-any.whl.
File metadata
- Download URL: asp_selftest-0.0.31-py3-none-any.whl
- Upload date:
- Size: 50.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72ccb2b0ef95ed879d41e84d33a9447c6f40d7ee7ef10dda7569302c2ee58252
|
|
| MD5 |
f460adbab98b830d8883029e58228092
|
|
| BLAKE2b-256 |
eb93f1a90fe4a641cf2197976ca447cf69e7cf63c84db80593eecf393cb689db
|