Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
zkessin committed Jan 28, 2014
2 parents 39555fc + 26c9854 commit e13c20c
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
30 changes: 30 additions & 0 deletions 05_proper.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,33 @@ The other issue is that both proper and eunit define a macro
include proper before eunit, or you could just have the PropER and
EUnit tests in seperate modules.


=== Using Proper for Integration tests

So far we have covered the case where we are using Proper For what is
in effect unit testing, where we want to ensure that the logic of some
application is correct.

But what if we wish to ensure that for example our connection to the
database is working well. In this case we have an obvious set of
properties that we can exploit, in that we can test that the round
trip to the database works. If we Create a Record, write it to the
database, then read it back from the database it should be the same
(with the possible excpetion of ID columns and timestamps.

In doing this for the Chicago Boss I discovered a major bug in the
MySQL integration. I found that the escaping of strings was not being
done correctly. If you saved the string "\\ " it would strip out the 2
backslashes. I don't think I would have found this by manual testing
but proper found it in the first block of 100 tests. It actually found
it in a much larger string, but then reduced it down to the "\\ " that
I was able to test. Once I had found the problem then actually solving
it was pretty easy.

As for how I solved it I connected boss to a mysql virtual machine
and had a table with the correct fields. Then I used this

[source,erlang]
----
include::proper/mysql_test.erl]
----
59 changes: 59 additions & 0 deletions proper/mysql_test.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-module(mysql_test).
-compile(export_all).
-include("deps/proper/include/proper.hrl").



runp() ->
runp(100).

runp(N) ->
proper:quickcheck(prop_postgres_update_round_trip(),[N]),
ok.

-type ascii_char() ::32..126.
prop_postgres_round_trip() ->
?FORALL({Text, Integer, Bool, Float, Date,Bytea},
{list(ascii_char()),
integer(),
boolean(),
float(),
date(),binary()},
?IMPLIES(calendar:valid_date(Date),
?IMPLIES(length(Text) > 1,
begin
test_round_trip({tb(Text),Integer, Bool, Float, Date, Bytea})
end))).
test_round_trip({Text,Integer, Bool, Float, Date, Bytea}) ->
Rec = db_test:new(id, Text, Integer, Bool, Float, Date, Bytea),

{ok, Rec2} = Rec:save(),

[R|_] = boss_db:find(db_test, [{text, 'equals', Text}]),
io:format( "<-- ~p~n--> ~p~n~n",[Rec2, R]),

Res = all([
R:id() =:= Rec2:id(),
tb(R:text()) =:= tb(Rec:text()),
R:integer() =:= Rec:integer(),
cb(R:bool()) =:= Rec:bool(),
1.0* R:float() =:= Rec:float(),
R:date() =:= {date,Rec:date()},
R:bytea() =:= Rec:bytea()]),
boss_db:delete(Rec2:id()),
Res.

cb(0) ->
false;
cb(_) ->
true.

all(L) ->
lists:all(fun(X) ->
X
end, L).

tb(X) when is_list(X) ->
list_to_binary(X);
tb(X) when is_binary(X) ->
X.

0 comments on commit e13c20c

Please sign in to comment.