为基于 属性 的测试生成随机规则

Generating a random rule for property based test

我正在使用 Triq(erlang quickcheck),但我无法为我的程序生成一组 nice 规则。

我想要生成的东西看起来像这样:

A -> B

我想提供 AB 的大小,后者没有任何重复项。

例如,如果我说用 L.H.S 生成我的规则。 [a] 和 R.H.S。尺寸 4(即 A = [a]size(B) = 4)我想要这样的东西:

{rule, [a], [1,2,4,5]}
{rule, [a], [a,d,c,e]}
{rule, [a], [q,d,3,4]}

请注意,我不想在 B 中出现 任何 重复(这是我遇到问题的部分)。此外,B 由什么组成并不重要 - 它可以是任何东西,只要它是不同的并且没有重复即可。

我的规范太乱了,不能在这里展示,所以我不想展示。

我不熟悉 Triq,但在 PropEr 和 Quviq 的 Qickcheck 中,您可以使用 ?SUCHTHAT 条件过滤 'bad' 个实例。

如果生成的实例不满足 ?SUCHTHAT 约束,它将被丢弃并且不计为有效测试。您可以使用此机制生成指定大小的列表(即 PropEr 调用的列表 'vectors'),然后丢弃那些具有重复项的列表,但我认为随后会丢弃太多实例(另请参阅 link).

修改生成器通常更有效,这样 所有 个实例都是有效的,在您的情况下,例如生成 (3) X 倍的元素,删除重复项并根据需要保留尽可能多的元素。这个还是会失败,会失败,所以要防着。

这是适合您的案例的生成器,在 PropEr 中,还有一个虚拟机 属性:

-module(dummy).

-export([rule_prop/0]).

-include_lib("proper/include/proper.hrl").

-define(X, 5).

rule_prop() ->
  ?FORALL(_, rule_gen(integer(), 4, integer()), true).

rule_gen(A, SizeB, TypeB) ->
  ?LET(
     EnoughB,
     ?SUCHTHAT(
        NoDupB,
        ?LET(
           ManyB,
           vector(?X * SizeB, TypeB),
           no_dups(ManyB)
          ),
        length(NoDupB) >= SizeB
       ),
     begin
       B = lists:sublist(EnoughB, SizeB),
       {rule, A, B}
     end).

no_dups([]) ->
  [];
no_dups([A|B]) ->
  [A | no_dups([X || X <- B, X =/= A])].