Jen*_*sen 5 unit-testing module prolog composition swi-prolog
在我最后一个问题下方的评论中详细说明讨论:我正在寻找有关构建 SWI-Prolog 代码的技术或最佳实践的建议,以便能够使用和测试算法及其支持模块的替代、可互换实现。
当前情况可以使用以下虚构的小示例来说明:用户提供一些输入数据 (file data.pl) 并加载具有要应用的算法(file ) 的模块graph.pl。算法模块本身使用来自另一个模块(文件path.pl)的辅助谓词,而后者又需要访问用户提供的数据:
文件“ data.pl”(输入数据集):
:- use_module(graph).
edge(a,b).
edge(b,c).
edge(c,d).
Run Code Online (Sandbox Code Playgroud)
文件“ graph.pl”(算法):
:- module(graph, [reachable/2]).
:- use_module(path).
reachable(X,Y) :-
path(X,Y), !.
reachable(X,Y) :-
path(Y,X), !.
Run Code Online (Sandbox Code Playgroud)
文件“ path.pl”(带有辅助谓词的模块,注意它访问 中的数据user):
:- module(path, [path/2]).
path(X,X).
path(X,Y) :-
user:edge(X,Z),
path(Z,Y).
Run Code Online (Sandbox Code Playgroud)
对于将算法应用于单个输入数据集和算法的单个实现的用例,这完全没问题:
?- [data].
true.
?- reachable(a,a).
true.
?- reachable(a,d).
true.
?- reachable(d,a).
true.
Run Code Online (Sandbox Code Playgroud)
现在假设我有大量的数据集,以及graph和path模块的多个替代实现(具有相同的接口,即导出的谓词)。对于(小)举例的目的,让我们假设我们文件中的数据文件data1.pl,data2.pl,帮手谓语模块path1.pl,path2.pl和算法模块graph1,graph2.pl。
我想使用SWI-Prolog 单元测试自动测试这些,并且最好能够编写一个测试套件来支持不同的数据集和不同的模块实现,而无需在两者之间重新启动 Prolog。也就是说我希望能够测试笛卡尔积中的所有组合
{data1.pl, data2.pl} x {path1.pl, path2.pl} x {graph1.pl, graph2.pl}
没有复制粘贴/复制代码。
我的问题是:我将如何在 SWI-Prolog 中解决这个问题?是否有关于如何为此目的将代码组织成模块的最佳实践、设计模式等?我是否应该利用动态导入在替代算法模块之间切换,并在数据的单元测试中简单地使用setup和cleanup?
对于单元测试,绝对使用setup/1和cleanup/1,您希望您的测试用例与您的测试一起使用。
为了您自己的探索和灵活性,请重新调整您的依赖关系树,您不希望使用用户名称空间调用谓词,因为当您的导入变得更加复杂或发生变化时,它将不起作用。该算法依赖于实用谓词,而实用谓词需要它所操作的数据。
\n\n文件“data.pl”(输入数据集):
\n\n:- module(data, [edge/2]).\n\nedge(a,b).\nedge(b,c).\nedge(c,d).\nRun Code Online (Sandbox Code Playgroud)\n\n文件“graph.pl”(算法):
\n\n:- module(graph, [reachable/2]).\n:- use_module(path).\n\nreachable(X,Y) :-\n path(X,Y), !.\nreachable(X,Y) :-\n path(Y,X), !.\nRun Code Online (Sandbox Code Playgroud)\n\n文件“path.pl”(带有辅助谓词的模块,注意它访问所用模块中的数据):
\n\n:- module(path, [path/2]).\n:- use_module(data).\n\npath(X,X).\npath(X,Y) :-\n edge(X,Z),\n path(Z,Y).\nRun Code Online (Sandbox Code Playgroud)\n\n现在你可以swipl -g "reachable(a, d)" -s graph.pl。这将让您轻松更改path.pl. 如果您愿意,您可以使用谓词在此处动态加载模块,但最好在单元测试中使用设置/清理:
:- dynamic path:edge/2.\n\n/* Testing Graph\na\xe2\x86\x92b\xe2\x86\x92c\xe2\x86\x92d \n*/\nsetup :-\n asserta(path:edge(a,b)),\n asserta(path:edge(b,c)),\n asserta(path:edge(c,d)).\ncleanup :-\n retractall(path:edge(_, _)).\n\ntest(reach_same,\n [ true(A, a)\n , setup(setup)\n , cleanup(cleanup)\n , nondet\n ]\n ) :-\n reachable(a, A).\nRun Code Online (Sandbox Code Playgroud)\n