[erlang-questions] PropEr after test clean up

Hynek Vychodil <>
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 <> 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:
>
> :~/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-0001.html>
```