Property-Based Testing with PropEr, Erlang, Elixir の Chapter 3 です。
Thinking in Properties
あんまりきちんと中身見れていない。中項目として
- Modeling
- Generalizing Example Tests
- Invariants
- Symmetric Properties
とのこと。順に確認しつつ自分メモを。
Modeling
pbt/lib/pbt.ex
に biggest な定義を移動。
def biggest([head|tail]) do
biggest(tail, head)
end
def biggest([], max) do
max
end
def biggest([head|tail], max) when head >= max do
biggest(tail, head)
end
def biggest([head|tail], max) when head < max do
biggest(tail, max)
end
end
で、テスツなコードを以下に修正。
property "finds biggest element" do
forall x <- non_empty(list(integer())) do
Pbt.biggest(x) == model_biggest(x)
end
end
defp model_biggest(list) do
List.last(Enum.sort(list))
end
Modeling と言われてもむむむむ、となってしまうなぁ。
Generalizing Example Tests
こんなテスツを generalize とのこと。
last_test() ->
?assert(-23 =:= lists:last([-23]))
?assert(5 =:= lists:last([1,2,3,4,5]))
?assert(3 =:= lists.last([5,4,3]))
以下が例示されてます。
property "picks the last number" do
forall {list, known_last} <- {non_empty(list(number())), number()} do
known_list = list ++ [known_last]
known_last == List.last(known_list)
end
end
マジックナンバー減らせ、って話なのかどうか。そゆ意味では generator てのが強力ですね。
Invariants
lists:sort/1
をサンプルにいくつかテスツを、とのこと。最初に “a sorted list has all the numbers in it ordered from smallest to largest.” な確認を、なのかな。
property "a sorted list has ordered pairs" do
forall list <- list(term()) do
is_ordered(Enum.sort(list))
end
end
defp is_ordered([a, b|t]) do
a <= b and is_ordered([b|t])
end
defp is_ordered(_) do
true
end
あるいは
- sort 前と後のリストのサイズは同じ
- 要素は追加されていないこと
- 要素は削除されていないこと
を確認、とのこと。
property "a sorted list keeps its size" do
forall l <- list(number()) do
length(l) == length(Enum.sort(l))
end
end
property "no element added" do
forall l <- list(number()) do
sorted = Enum.sort(l)
Enum.all?(sorted, fn element -> element in l end)
end
end
property "no element deleted" do
forall l <- list(number()) do
sorted = Enum.sort(l)
Enum.all?(l, fn element -> element in sorted end)
end
end
Symmetric Properties
encode, decode な例。以下な試験を、とのこと。
property "symmetric encoding/decoding" do
forall data <- list({atom(), any()}) do
encoded = encode(data)
is_binary(encoded) and data == decode(encoded)
end
end
むむむむ的。。encode および decode の定義は以下とのこと。
def encode(t), do: :erlang.term_to_binary(t)
def decode(t), do: :erlang.binary_to_term(t)
あまりにも消化不良なので
練習問題やってみようかな。