/var/log/messages

Apr 30, 2019 - 2 minute read - Comments - programming

Property-Based Testing with PropEr, Erlang, Elixir (3)

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)

あまりにも消化不良なので

練習問題やってみようかな。

Property-Based Testing with PropEr, Erlang, Elixir (2) TODO?

comments powered by Disqus