Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.14 instead.
Reason given by maintainers: Invalid version number

asp-selftest

A unit testing framework for Answer Set Programming (ASP) that enables in-source test definitions and execution.

NB: clingo+ is now clingoy, as the + is no longer allowd by Python packaging.

Overview

asp-selftest extends the Clingo ASP solver with integrated testing capabilities, allowing developers to write and execute unit tests directly within their logic programs. Tests are defined using standard ASP syntax and executed in isolated contexts to ensure reliability and maintainability.

Quick Start

Installation

pip install asp-selftest

Basic Usage

clingoy examples/edges.lp --run-asp-tests

Core Concepts

In-Source Unit Testing

Tests are embedded directly in ASP source files using #program directives. Consider the following example from nodes.lp:

% Implicit 'base' program

% Infer nodes from given edges.
node(A)  :-  edge(A, _).
node(B)  :-  edge(_, B).

% Verify that at least one edge exists.
cannot("at least one edge")  :-  not { edge(_, _) } > 0.


#program test_edge_leads_to_nodes(base).

% Test data: a simple graph with one edge.
edge(x, y).

% Assertions: verify expected node inference.
cannot("node x")  :-  not node(x).
cannot("node y")  :-  not node(y).
cannot("node z")  :-  not node(z).  % This assertion will fail

The cannot Predicate

The framework uses cannot predicates as inverted assertions. This design leverages ASP's constraint mechanism to avoid optimization issues that would affect traditional positive assertions.

As of version v0.1.6 cannot supports two arguments. This is usefull for tracking which values make a cannot fail. Suppose we want to ensure that for every node N a color is defined with node_color:

cannot("undefined node color", N)  :-  node(N), not node_color(N, _).

Now we can see in the error message for which node N there is no color.

Execution Example:

$ clingoy nodes.lp --run-asp-tests
...
Reading from nodes.lp
Testing nodes.lp
  test_edge_leads_to_nodes(base)
...
AssertionError: cannot("node z")
File nodes.lp, line 11, in test_edge_leads_to_nodes(base). Model follows.
edge(x,y)
node(x)
node(y)

The test fails because node(z) does not exist in the model. To correct this assertion:

cannot("node z")  :-  node(z).

Validating Base Programs

After unit tests pass, the framework validates the base program. If prerequisites are missing, appropriate errors are reported:

$ clingoy nodes.lp --run-asp-tests
...
AssertionError: cannot("at least one edge")
File nodes.lp, line ?, in base. Model follows.
<empty model>

Adding the required data file resolves the issue:

$ clingoy nodes.lp edges.lp --run-asp-tests
...
Testing nodes.lp
  test_edge_leads_to_nodes(base)
Testing edges.lp
Testing base
  base
Solving...
Answer: 1 (Time: 0.003s)
edge(a,b) node(b) node(a)
SATISFIABLE

Test Dependencies

Tests and their dependencies are specified using #program directives. Test names must begin with the test_ prefix. Formal parameters declare dependencies on other program units:

#program unit_A.
    
#program test_unit_A(base, unit_A).

The implicit base program1 must be explicitly referenced when required as a dependency. Actual arguments to test programs are not defined.

Test Scoping

The framework enforces strict test isolation:

  • Tests in each file execute within the context of that file only
  • When file A includes file B:
    • Tests in B execute with only B's logic loaded
    • Tests in A execute with both A's and B's logic loaded

This scoping ensures that tests remain independent and do not interfere with each other.

Error Reporting

The framework provides clear, actionable error messages for syntax and semantic errors:

$ clingoy 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).

Understanding cannot Predicates

The framework uses cannot predicates rather than positive assertions for technical reasons related to ASP's optimization behavior. Traditional positive assertions can be optimized away by the solver, requiring complex idioms to prevent this. The cannot approach leverages ASP's constraint mechanism1 for more reliable testing.

Technical Background

In ASP, constraints are headless rules that must always evaluate to false. When a constraint becomes true, the runtime considers the model invalid. The natural reading of a constraint is: "it cannot be the case that..."

By using cannot as a predicate head rather than a constraint, the framework allows these predicates to appear in models when they become true. The test runner then inspects the model and raises errors for any cannot predicates present.

Example without test execution:

$ clingoy logic.lp
clingoy version 5.8.0
Reading from logic.lp
Solving...
Answer: 1 (Time: 0.001s)
cannot("at least one edge")
SATISFIABLE

The cannot predicate appears in the model, which the test runner would flag as a failure. This approach provides a straightforward testing mechanism: if you can write ASP constraints, you can write cannot assertions.

Architecture

Plugin System

asp-selftest is built on a flexible plugin architecture that enables modular extension and customization of the testing framework. The plugin system uses a functional composition pattern where each plugin wraps the next in a processing chain, allowing for clean separation of concerns and easy extensibility.

The core plugin chain includes:

  • clingo_main_plugin: Provides CLI integration and argument handling
  • stdin_to_tempfile_plugin: Manages input from stdin by converting it to temporary files
  • clingo_syntaxerror_plugin: Enhances error messages with rich formatting and context
  • clingo_sequencer_plugin: Orchestrates the standard Clingo workflow (Load → Ground → Solve)
  • testrunner_plugin: Discovers and executes tests, enforcing isolation and dependency management
  • clingo_reify_plugin: Provides ASP reification support for advanced meta-programming
  • clingo_defaults_plugin: Configures default behaviors and settings

Each plugin receives the next plugin in the chain as its first argument and can intercept, modify, or enhance the processing pipeline. This architecture allows developers to extend the framework with custom plugins for specialized testing scenarios or integration with other tools.

Project Status

asp-selftest is actively maintained and used in a production environment. The framework has been successfully deployed for formal specification of railway interlocking systems, comprising 35 files, over 100 tests, and more than 600 assertions.

The project was presented at Declarative Amsterdam in November 2024.

Installation and Usage

Installation

pip install asp-selftest

Running ASP Tests

clingoy <file.lp> --run-asp-tests

Running Python Tests

The framework includes support for in-source Python tests:

clingoy --run-python-tests

Requirements

  • Python 3.13 or higher
  • Clingo 5.8.0 or higher

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

Contributing

Contributions are welcome. Please ensure that all tests pass before submitting pull requests.

Repository

This project has been migrated from GitHub to Codeberg.

  1. Potassco User Guide §3.1.2 2

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asp_selftest-1.12.tar.gz (48.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asp_selftest-1.12-py3-none-any.whl (54.1 kB view details)

Uploaded Python 3

File details

Details for the file asp_selftest-1.12.tar.gz.

File metadata

  • Download URL: asp_selftest-1.12.tar.gz
  • Upload date:
  • Size: 48.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for asp_selftest-1.12.tar.gz
Algorithm Hash digest
SHA256 f98d2321a54135177cd065602dcb952a26739ecaab947edd80a5a6be58a656e4
MD5 84481dccb568defa3e2972ffd1e5730b
BLAKE2b-256 1d2bc6870f0ec87fd61ecfb13a4f02f074982f66998cc638b4234702fb8d9e30

See more details on using hashes here.

File details

Details for the file asp_selftest-1.12-py3-none-any.whl.

File metadata

  • Download URL: asp_selftest-1.12-py3-none-any.whl
  • Upload date:
  • Size: 54.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for asp_selftest-1.12-py3-none-any.whl
Algorithm Hash digest
SHA256 edd5080029b469a1bc2dde9e93862fd245dfbfac090fed1d927266fbaf216a30
MD5 94a63e1db88181a07008d47d83ea3b4f
BLAKE2b-256 f5088ca43e803be7cfd04d9e68ef6f814be6b5238a8e81cf55af906fb7e6ca71

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.12 This release

2 files

0.1.14

2 files

0.1.13

2 files

0.1.11

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.0.31

2 files

0.0.30

2 files

0.0.21

2 files

0.0.20

2 files

0.0.18

2 files

0.0.17

2 files

0.0.16

2 files

0.0.15

2 files

0.0.14

2 files

0.0.13

2 files

0.0.12

1 file

0.0.11

2 files

0.0.10

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page