Генерация случайного правила для теста на основе свойств

Я использую Triq ( erlang quickcheck), и у меня возникают проблемы при создании наборахороших правил для моей программы.

То, что я хочу генерировать, это вещи, которые выглядят так:

A -> B

где я хотел бы предоставить Aи размерBс последним, не имеющим дубликатов.

Например, если я скажу, сгенерируйте мне правила с LHS [a]и RHS размера 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 ответ

Решение

Я не знаком с Triq, но в PropEr и Quviq's 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])].
Другие вопросы по тегам