euc2003
Thomas Arts
thomas.arts@REDACTED
Fri Nov 21 15:48:16 CET 2003
Hi Luke
As Björn already pointed out, the version does handle recursive
datatypes definitions. A manual would have been useful ;-/.
A generator should be made such that it does not generate an
infinite datastructure. This is solved by first selecting a random
number (i.e. number of applications of constructor rules) and
then building the datatype of that size. The Size parameter should
decrease with at least 1 in every recursive call in the
generation.
In that sense, the function below seems to me still able to
produce an infinite datastructure:
> gb_set() ->
> ?SIZED(N, resize(min(50, N),
> frequency(
> [{6,?LET(L, list(int()),
> return({'@',gb_sets,from_list,[L]}))},
> {6,?LET(L, list(int()),
> return({'@',gb_sets,from_ordset,[{'@',ordsets,from_list,[L]}]}))},
> {6,?LET(S,gb_set(),?LET(E,int(),
> return({'@',gb_sets,add,[E,S]})))},
> {2,return({'@',gb_sets,empty,[]})},
> {2,?LET(E,int(),
> return({'@',gb_sets,singleton,[E]}))},
> {1,?LET(P,function(bool()),?LET(S,gb_set(),
> return({'@',gb_sets,filter,[P,S]})))}
> ]))).
A better definition would be
gd_set() ->
?SIZED(Size,gd_set(Size)).
gd_set(Size) ->
frequency(
[{6,?LET(L, list(int()),
return({'@',gb_sets,from_list,[L]}))},
{6,?LET(L, list(int()),
return({'@',gb_sets,from_ordset,[{'@',ordsets,from_list,[L]}]}))},
{6,?LET(S,gb_set(Size-1), % change here
?LET(E,int(),
return({'@',gb_sets,add,[E,S]})))},
{2,return({'@',gb_sets,empty,[]})},
{2,?LET(E,int(),
return({'@',gb_sets,singleton,[E]}))},
{1,?LET(P,function(bool()),?LET(S,gb_set(Size-1), % change here
return({'@',gb_sets,filter,[P,S]})))}
]).
Note that this Size is NOT the size of the set (i.e. number of elements),
but
the number of applications of a function to construct a set. Moreover, it is
a kind of maximum number of applications, since if the non-recursive branch
is chosen, the size will be less.
If you now feel that this set is too small for a certain property, you could
resize it for testing that property, e.g.:
instead of
prop_not_empty() ->
?FORALL(X,gb_set(),
?IMPLIES(gb_sets:size(X) /= 0, not gb_sets:is_empty(X))).
one can use:
prop_not_empty() ->
?FORALL(X,resize(80,gb_set()),
?IMPLIES(gb_sets:size(X) /= 0, not gb_sets:is_empty(X))).
Note that the sets are bigger and testing takes longer.
If you find that the numbers in the sets are to restricted, i.e., you
only get sets with elements between -20 and +20, then you can do the
following
in the gd_set definition:
gd_set(Size) ->
frequency(
[{6,?LET(L, list(resize(2000,int())),
return({'@',gb_sets,from_list,[L]}))},
{6,?LET(L, list(resize(2000,int())),
return({'@',gb_sets,from_ordset,[{'@',ordsets,from_list,[L]}]}))},
{6,?LET(S,gb_set(Size-1), % change here
?LET(E,resize(2000,int()),
return({'@',gb_sets,add,[E,S]})))},
{2,return({'@',gb_sets,empty,[]})},
{2,?LET(E,int(),
return({'@',gb_sets,singleton,[E]}))},
{1,?LET(P,function(bool()),?LET(S,gb_set(Size-1), % change here
return({'@',gb_sets,filter,[P,S]})))}
]).
making the integers taken from a larger interval.
Similar, one can take larger lists as generators by writing
resize(100,list()).
Hope this clarifies a bit our thoughts. John and I are going to
write a paper about quickcheck and make some documentation
and examples as soon as time permits.
Cool that we got so much positive feedback on this application!
Thomas
---
Dr Thomas Arts
Program Manager
Software Engineering and Management
IT-university in Gothenburg
Box 8718, 402 75 Gothenburg, Sweden
http://www.ituniv.se/
Tel +46 31 772 6031
Fax +46 31 772 4899
More information about the erlang-questions
mailing list