首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在SWI-Prolog中声明仅在单个单元测试范围内为真的事实

在SWI-Prolog中声明仅在单个单元测试范围内为真的事实
EN

Stack Overflow用户
提问于 2015-02-28 04:17:40
回答 2查看 205关注 0票数 2

作为这个问题的一个例子,我有一个非常简单的Prolog文件main.pl,在其中我定义了一些形状的颜色。

代码语言:javascript
复制
colour(circle, red).
colour(triangle, red).
colour(square, blue).

现在,我在下面定义了一个谓词same_colour/2,如果S1S2是相同的颜色,则该谓词为真。

代码语言:javascript
复制
same_colour(S1, S2) :-
    colour(S1, C),
    colour(S2, C).

在顶层进行的测试表明,此谓词的工作方式与预期一致。

代码语言:javascript
复制
?- same_colour(circle, triangle).
true.

?- same_colour(circle, square).
false.

我正在尝试使用适用于same_colour/2的SWI-Prologs单元测试框架plunit编写单元测试,但我希望在每个单独的测试中声明只有在该测试范围内才为真的事实。我尝试过对单个测试使用setup选项,也尝试使用asserta选项,但这两种方法都不起作用。下面的所有测试都失败了。

代码语言:javascript
复制
:- 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).

我也尝试过:

代码语言:javascript
复制
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) (或者至少在我的测试运行时不是真的)。

代码语言:javascript
复制
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

我现在可以理解为什么前两个测试不起作用了。在第一个测试中,我测试colour(shape_a, colour_1)是否为真,而在第二个测试中,我认为在谓词定义中使用asserta是不正确的。虽然感觉和我的第三次或第四次测试类似,但应该能够实现我想要做的事情?

EN

回答 2

Stack Overflow用户

发布于 2015-02-28 15:20:20

测试您的测试:)

代码语言:javascript
复制
:- 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).

收益率

代码语言:javascript
复制
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.

也就是说,如果您想在运行时修改数据库,请让Prolog知道,并添加:

代码语言:javascript
复制
:- dynamic colour/2.

现在变得更好了:

代码语言:javascript
复制
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.

但是数据库是“脏的”:

代码语言:javascript
复制
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.

当然,很久以前就知道,在运行时修改程序是一种危险的活动……无论如何,设置/清理都是目标,所以也许你想

代码语言:javascript
复制
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).
票数 2
EN

Stack Overflow用户

发布于 2015-02-28 20:47:07

您有一个在alternative Logtalk的单元测试框架中使用的简单解决方案:

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

SWi-Prolog是12个受支持的Prolog系统之一。不需要使用dynamic/1指令或清理目标进行黑客攻击。

例如,假设您有三组要用来测试代码的事实。此外,假设要测试的代码是在same_color.pl Prolog文件中定义的。只需为每组事实定义一个单元测试对象:

代码语言:javascript
复制
:- object(colors1, extends(lgtunit)).

    :- include('same_color.pl').

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

    test(colors1) :-
        ...

:- end_object.

定义对象,例如其他事实集的colors2colors3。然后:

代码语言:javascript
复制
| ?- logtalk_load(lgtunit(loader)).
...
| ?- logtalk_load([colors1, colors2, colors3], [hook(lgtunit)]).
...
| ?- colors1::run, colors2::run, colors3::run.

或者简单地通过定义一个tester.lgt帮助文件并运行logtalk_tester自动化外壳脚本来自动化单元测试。有很多示例,包括Logtalk发行版中的示例tester-sample.lgt文件。如果您觉得使用Logtalk单元测试工具测试Prolog代码很奇怪,请了解Logtalk发行版包括一个完整的Prolog标准一致性测试套件,它为您提供了更多示例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28773539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档