Andrew Rosa
May 26, 2019
120

Apesar de ser uma ferramenta poderosa, Teste Baseado em Propriedades é muito pouco aplicado. Vou falar um pouco sobre a técnica e seus trade-offs, ferramentas para Elixir e contar um pouco sobre como estamos aplicando em nossos micro-serviços, stateful.

May 26, 2019

## Transcript

13. ### test "sorts a list" do assert Enum.sort([3, 1, 2]) ==

[1, 2, 3] end
14. ### test "sorts a list" do assert Enum.sort([3, 1, 2]) ==

[1, 2, 3] end
15. ### test "sorts a list" do assert Enum.sort([3, 1, 2]) ==

[1, 2, 3] end

end
17. ### test "sorts an empty list" test "sorts a list with

a single item" test "sorts a list multiple equal items" test "sorts a list huge numbers" test "sorts a list negative numbers" test "sorts a big list with lots of items"

19. ### property "sorts a list" do forall x <- list(integer()) do

Enum.sort(x) |> Enum.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a <= b end) end end
20. ### property "sorts a list" do forall x <- list(integer()) do

Enum.sort(x) |> Enum.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a <= b end) end end
21. ### property "sorts a list" do forall x <- list(integer()) do

Enum.sort(x) |> Enum.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a <= b end) end end

23. ### property "sorts a list" do forall x <- list(integer()) do

Enum.sort(x) |> Enum.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a <= b end) end end

29. ### property "sorts a list" do forall unsorted <- list(integer()) do

unsorted |> Enum.chunk_every(2, 1, :discard) |> Enum.all?(fn [a, b] -> a <= b end) end end

34. ### forall cmds <- commands(TestModel) do {history, state, result} = run_commands(TestModel,

cmds) (result == :ok) |> aggregate(command_names(cmds)) |> when_fail(& report(cmds, state, result, history)) end
35. ### forall cmds <- commands(TestModel) do {history, state, result} = run_commands(TestModel,

cmds) (result == :ok) |> aggregate(command_names(cmds)) |> when_fail(& report(cmds, state, result, history)) end

47. ### def command(%{ongoing: ids}) do [ {:call, TestShim, :answer, [elements(ids)]}, {:call,

TestShim, :hangup, [elements(ids)]} ] |> oneof() end

49. ### def next_state(state, call_id, {:call, _, :dial, [number]}) do state |>

acquire_call(call_id, number) |> set_call_state(call_id, :ringing) end
50. ### forall cmds <- commands(TestModel) do {history, state, result} = run_commands(TestModel,

cmds) (result == :ok) |> aggregate(command_names(cmds)) |> when_fail(& report(cmds, state, result, history)) end

end end

end end

57. ### defmodule TestShim do def dial(number) do # build client and

payload  case Tesla.post(client, "/dial", payload) do # process response and return call_id end end end

true end

62. ### defmodule TestShim do use GenServer def dial(number) do  GenServer.call( __MODULE

__, {:dial, number}) end end
63. ### def handle_call({:command, :dial, number}, from, state) do {:ok, call_id} =

CallControl.dial(number) # update state {:noreply, state} end
64. ### def handle_cast({:webhook, webhook, call_id, resp}, state) do # descobre `ref`

a partir dos parâmetros if ref, do: GenServer.reply(ref, resp) {:noreply, state} end

66. ### forall cmds <- commands(TestModel) do TestShim.setup_parties() {history, state, result} =

run_commands(TestModel, cmds) (result == :ok) |> aggregate(command_names(cmds)) |> when_fail(& report(cmds, state, result, history)) end
67. ### forall cmds <- commands(TestModel) do TestShim.setup_parties() {history, state, result} =

run_commands(TestModel, cmds) (result == :ok) |> aggregate(command_names(cmds)) |> when_fail(& report(cmds, state, result, history)) end

74. ### def next_state(state, _, {:call, _, :setup_parties, []}) do %{available: state[:init],

ongoing: %{}, busy: %{}} end

end