[erlang-questions] PropEr after test clean up
Hynek Vychodil
vychodil.hynek@REDACTED
Tue May 26 11:34:41 CEST 2015
I think you are missing the point. Let's demonstrate the problem in this
way. There is natural but not working way how to do it
-define(WITH_G(L, Do),
begin
G = Module:from_edgelist(L),
try Do after delete(G)
end
end
).
-define(WITH_G(L, DoEmpty, DoOther),
?WITH_G(L,
case L of
[] -> DoEmpty;
_ -> DoOther
end
)
).
prop_vertices(Module) ->
?FORALL(
L, digraph(),
?WITH_G(
L, equals([], vertices(G)),
?FORALL(
{V1, V2}, oneof(L),
conjunction(
[{source, lists:member(V1, vertices(G))},
{sink, lists:member(V2, vertices(G))},
{in_sources, lists:member(V1, sources(G))},
{in_sinks, lists:member(V2, sinks(G))}
]
)
)
)
).
And how to make it work:
prop_vertices(Module) ->
?FORALL(
L, digraph(),
case L of
[] -> ?WITH_G(L, equals([], vertices(G)));
_ ->
?FORALL(
{V1, V2}, oneof(L),
?WITH_G(L,
begin
Vs = vertices(G),
Ses = sources(G),
Sks = sinks(G),
conjunction(
[{source, lists:member(V1, Vs)},
{sink, lists:member(V2, Vs)},
{in_sources, lists:member(V1, Ses)},
{in_sinks, lists:member(V2, Sks)}
]
)
end
)
)
end
).
There is the problem. There is no way you can write ?WITH_G macro working
with any of PropEr macros as a parameter. And it would have a simple
solution. Just spawn the process or add hooks for clean up.
I know it is possible to write it in a way it will work, but it prevents to
write it reliably and in structured way.
On Tue, May 26, 2015 at 1:44 AM, Kostis Sagonas <kostis@REDACTED> wrote:
> On 05/25/2015 05:11 PM, Hynek Vychodil wrote:
>
>>
>> I bumped in the problem how clean up after property in PropEr. Let's
>> have simple property where I make ets table:
>>
>> prop_ets() ->
>> ?FORALL(V, integer(),
>> begin
>> E = ets:new(),
>> true = ets:insert(T, {V, ok}),
>> equals([{V, ok}], ets:lookup(T, V))
>> end
>> ).
>>
>> How am I supposed to delete ets table? It is trickier than looks like.
>> ... <SNIP>
>>
>
> I am not sure I understand what it is exactly that you are finding
> difficult to do in the simple example above. Here is how:
>
> =====================================================================
> -module(pets).
> -include_lib("proper/include/proper.hrl").
>
> -export_type([key/0, val/0]). % shut off compiler warning
>
> -type key() :: a | b | c.
> -type val() :: 0..42.
>
> prop_ets() ->
> ?FORALL({K,V}, {key(),val()},
> begin
> T = setup(),
> true = ets:insert(T, {K, V}),
> Res = ets:lookup(T, K),
> cleanup(T),
> [{K, V}] =:= Res
> end).
>
> setup() ->
> ets:new(?MODULE, [public, named_table]).
>
> cleanup(T) ->
> ets:delete(T).
> ========================================================================
>
> The pattern of doing a setup, running some commands and getting some
> Result, doing the cleanup you want to do, and the check that the result is
> the one that you expect is a general pattern in property-based testing.
>
> As you can see, the above works:
>
> kostis@REDACTED:~/proper$ erl -pa ~/proper
> Erlang/OTP 17 [erts-6.4.1] [source] [64-bit] [smp:8:8] [async-threads:10]
> [hipe] [kernel-poll:false]
>
> Eshell V6.4.1 (abort with ^G)
> 1> c(pets, [debug_info]).
> {ok,pets}
> 2> proper:quickcheck(pets:prop_ets()).
>
> ....................................................................................................
> OK: Passed 100 test(s).
> true
>
>
> Change the property to one that does not hold (e.g. [{K, V}] =/= Res) and
> you will also see that shrinking works.
>
>
> I am not sure I follow what you mean by your nested ?FORALL properties but
> note that, as shown above, you can easily imitate multiple ?FORALLs by
> using complex terms (tuples, lists, etc.).
>
> Hope this helps,
> Kostis
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150526/b8864d49/attachment.htm>
More information about the erlang-questions
mailing list