# Testing for nondeterminism in plunit

**URL:** <https://swi-prolog.discourse.group/t/testing-for-nondeterminism-in-plunit/2350>\
**Category:** Request For Comments\
**Tags:** discussion\
**Created:** [May 17, 2020, 12:24pm UTC](https://swi-prolog.discourse.group/t/testing-for-nondeterminism-in-plunit/2350 "2020-05-17T12:24:04Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![dtonhofer](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dtonhofer/32/902_2.png) [@dtonhofer](https://swi-prolog.discourse.group/u/dtonhofer)\
**Post date:** [May 17, 2020, 12:24pm UTC](https://swi-prolog.discourse.group/t/testing-for-nondeterminism-in-plunit/2350/1 "2020-05-17T12:24:05Z")

</div>

Suppose I have the following. `naive_member/2` is nondeterministic on the last member, and I want to make the [plunit](https://eu.swi-prolog.org/pldoc/doc_for?object=section(%27packages/plunit.html%27)) tests fail if that occurs (both on “single tests” and on “all” tests).

How to do that?

```prolog
naive_member(X,[X|_]).
naive_member(X,[_|R]) :- naive_member(X,R).

:- begin_tests(member_determinacy).

% option "nondet" suppresses warning "Test succeeded with choicepoint"
% (it is not a test failure if the test succeeds with a choicepoint)

test(one_nondet) :- naive_member(1,[1,2,3]). % generates a warning
test(one,[nondet]) :- naive_member(1,[1,2,3]).
test(two,[nondet]) :- naive_member(1,[1,1,3]).
test(three,[nondet]) :- naive_member(1,[1,1,1]).
test(five,fail) :- naive_member(3,[1,1,2]).

% I want four_a to fail - How?

test(four_a,[nondet]) :- naive_member(2,[1,1,2]). % nondeterministic on last member
test(four_b) :- member(2,[1,1,2]). % deterministic on last member, needs no option

% Always work, indistinguishable from member/2, but what if I want four_all_a to fail if it leaves a 
% choicepoint open?

test(one_all_a ,all(M=[1])) :- naive_member(M,[1,2,3]),M=1.
test(two_all_a ,all(M=[1,1])) :- naive_member(M,[1,1,3]),M=1.
test(three_all_a,all(M=[1,1,1])) :- naive_member(M,[1,1,1]),M=1.
test(four_all_a ,all(M=[2])) :- naive_member(M,[1,1,2]),M=2.

% Always work

test(one_all_b ,all(M=[1])) :- member(M,[1,2,3]),M=1.
test(two_all_b ,all(M=[1,1])) :- member(M,[1,1,3]),M=1.
test(three_all_b,all(M=[1,1,1])) :- member(M,[1,1,1]),M=1.
test(four_all_b ,all(M=[2])) :- member(M,[1,1,2]),M=2.

:- end_tests(member_determinacy).

rt :- run_tests(member_determinacy).

```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [May 17, 2020, 2:57pm UTC](https://swi-prolog.discourse.group/t/testing-for-nondeterminism-in-plunit/2350/2 "2020-05-17T14:57:33Z")

</div>

The first set is what this is all intended to do.

I see no reason why would want to verify that a predicate succeeds and leaves a choice point (but no second answer). If you want to know whether it can produce multiple answers use the `all` recipe.

In the very unlikely case you want to test success is `nondet`, do

```prolog
    call_cleanup(test_supposed_to_be_nondet, Det=true),
    assertion(var(Det)).

```

The `all` tests are supposed to run findall/3, so no non-determinism will be left.
