2

この質問の例として、main.plいくつかの形状の色を定義した非常に単純な Prolog ファイルがあります。

colour(circle, red).
colour(triangle, red).
colour(square, blue).

その下で、 predicate を定義します。これは、とが同じ色のsame_colour/2場合に true です。S1S2

same_colour(S1, S2) :-
    colour(S1, C),
    colour(S2, C).

トップレベルでのテストは、この述語が期待どおりに機能することを示しています。

?- same_colour(circle, triangle).
true.

?- same_colour(circle, square).
false.

SWI-Prologs 単体テスト フレームワークplunit forを使用して単体テストを作成しようとしてsame_colour/2いますが、個々のテスト内で、そのテストの範囲内でのみ真である事実を宣言したいと考えています。setup個々のテストのオプションと を使用してみましたがasserta、どちらも機能しません。以下のテストはすべて失敗します。

:- begin_tests(same_colour).

test(same_colour) :-
    colour(shape_a, colour_1),
    colour(shape_b, colour_1),
    same_colour(shape_a, shape_b).

test(same_colour) :-
    asserta(colour(shape_a, colour_1)),
    asserta(colour(shape_b, colour_1)),
    same_colour(shape_a, shape_b).

test(same_colour, [
    setup(colour(shape_a, colour_1)),
    setup(colour(shape_b, colour_1))
]) :-
    same_colour(shape_a, shape_b).

:- end_tests(same_colour).

私も試しました:

test(same_colour, [
    setup(asserta(colour(shape_a, colour_1))),
    setup(asserta(colour(shape_b, colour_1))),
    cleanup(retract(colour(shape_a, colour_1))),
    cleanup(retract(colour(shape_b, colour_1)))
]) :-
    same_colour(shape_a, shape_b).

つまり、最初にcolour(shape_a, colour_1)colour(shape_b, colour_1)が事実であることを宣言し、テストを実行してから、それらを「宣言解除」します。ただし、このテストも失敗します。それを使用すると、決してアサートされないtraceようですcolour(shape_a, colour_1)(または、少なくともテストの実行中は真実ではありません)。

Call: (18) plunit_same_colour:'unit body'('same_colour@line 13', vars) ? creep
Call: (19) same_colour(shape_a, shape_b) ? creep
Call: (20) colour(shape_a, _G738) ? creep
Fail: (20) colour(shape_a, _G738) ? creep
Fail: (19) same_colour(shape_a, shape_b) ? creep
Fail: (18) plunit_same_colour:'unit body'('same_colour@line 13', vars) ? creep

最初の 2 つのテストが機能しない理由がわかりました。前に宣言されていない場合、最初に私colour(shape_a, colour_1)は真であるかどうかをテストしていassertaます. 3 回目または 4 回目のテストに似たような気がしますが、私がやろうとしていることを達成できるはずですか?

4

2 に答える 2

2

テストをテストする:)

:- module(colour_test, [same_colour/2]).
:- use_module(library(plunit)).

colour(circle, red).
colour(triangle, red).
colour(square, blue).

same_colour(S1, S2) :-
    colour(S1, C),
    colour(S2, C).

:- begin_tests(same_colour).

test(same_colour) :-
    colour(shape_a, colour_1),
    colour(shape_b, colour_1),
    same_colour(shape_a, shape_b).

test(same_colour) :-
    asserta(colour(shape_a, colour_1)),
    asserta(colour(shape_b, colour_1)),
    same_colour(shape_a, shape_b).

test(same_colour, [
    setup(colour(shape_a, colour_1)),
    setup(colour(shape_b, colour_1))
]) :-
    same_colour(shape_a, shape_b).

:- end_tests(same_colour).

収量

1 ?- run_tests(same_colour).
% PL-Unit: same_colour 
ERROR: /home/carlo/prolog/so/colour_test.pl:14:
    test same_colour: failed

ERROR: /home/carlo/prolog/so/colour_test.pl:19:
    test same_colour: received error: asserta/1: No permission to modify static procedure `colour_test:colour/2'
Defined at /home/carlo/prolog/so/colour_test.pl:4
ERROR: goal unexpectedly failed: colour(shape_a,colour_1)
 done
% 2 tests failed
% 0 tests passed
false.

つまり、実行時に DB を変更する場合は、Prolog に以下を追加して知らせます。

:- dynamic colour/2.

今は良くなっています:

2 ?- run_tests(same_colour).
% PL-Unit: same_colour 
ERROR: /home/carlo/prolog/so/colour_test.pl:16:
    test same_colour: failed

.. done
% 1 test failed
% 2 tests passed
false.

しかし、DBは「ダーティ」です:

3 ?- listing(colour).
:- dynamic colour_test:colour/2.

colour_test:colour(shape_b, colour_1).
colour_test:colour(shape_a, colour_1).
colour_test:colour(circle, red).
colour_test:colour(triangle, red).
colour_test:colour(square, blue).

true.

もちろん、実行時にプログラムを変更することは危険な行為であることは長い間知られています...とにかく、セットアップ/クリーンアップは目標なので、おそらくあなたが望むかもしれません

test(same_colour, [
    setup(( assertz(colour(shape_a, colour_1)),
            assertz(colour(shape_b, colour_1))
    )),
    cleanup(retractall(colour(_, colour_1)))
]) :-
    same_colour(shape_a, shape_b).
于 2015-02-28T07:20:19.863 に答える
1

代わりの Logtalk の単体テスト フレームワークを使用する簡単なソリューションがあります。

https://github.com/LogtalkDotOrg/logtalk3/blob/master/tools/lgtunit/NOTES.md

SWi-Prolog は、サポートされている 12 の Prolog システムの 1 つです。ディレクティブを使用したハックdynamic/1やクリーンアップの目標は必要ありません。

たとえば、コードのテストに使用するファクトのセットが 3 つあるとします。さらに、テストするコードがsame_color.plProlog ファイルで定義されているとします。ファクトの各セットごとに単体テスト オブジェクトを定義するだけです。

:- object(colors1, extends(lgtunit)).

    :- include('same_color.pl').

    colour(circle, red).
    colour(triangle, red).
    colour(square, blue).

    test(colors1) :-
        ...

:- end_object.

オブジェクトを定義します。たとえばcolors2colors3その他のファクトのセットを定義します。それで:

| ?- logtalk_load(lgtunit(loader)).
...
| ?- logtalk_load([colors1, colors2, colors3], [hook(lgtunit)]).
...
| ?- colors1::run, colors2::run, colors3::run.

tester.lgtまたは、ヘルプ ファイルを定義してlogtalk_tester自動化シェル スクリプトを実行することにより、単体テストを自動化します。tester-sample.lgtLogtalk ディストリビューションのサンプル ファイルを含む、多数の例。Logtalk 単体テスト ツールを使用して Prolog コードをテストするのがおかしいと思われる場合は、Logtalk ディストリビューションに完全な Prolog 標準準拠テスト スイートが含まれていることを知っておいてください。これにより、さらに例が提供されます。

于 2015-02-28T12:47:06.800 に答える