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

时间:2016-04-06 06:05:24

标签: erlang quickcheck triq

我正在使用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 由什么构成并不重要 - 它可以是任何东西,只要它是独特的并且没有重复。

我的规格太乱了,不能在这里展示,所以我宁愿不这样做。

1 个答案:

答案 0 :(得分:2)

我对Triq并不熟悉,但在PropEr和Quviq的Qickcheck中,您可以使用?SUCHTHAT条件来过滤“坏”'实例

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

通常更有效地修改生成器,以便所有实例都有效,在您的情况下,例如生成(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])].