エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Elixir 1.10 のアサーションの改善が、派手さはないけれどありがたい

このあいだ 1.9 がリリースされたと思っていたのに、もう 1.10 がリリースされました。

1.9 では、Elixir 単体でリリースを構築できるようになったり、config を一新したりと大きな変化がありましたが、それとくらべると今回あまり派手さを感じません。

それは Elixir が成熟期にさしかかっているということなのかもしれません。

そんな中でありがたい改善がありました。

リリースノートにも「小さいながら重要な改善」と書かれている ExUnit の改善です。

Other enhancements

ExUnit, our test framework, ships two small but important improvements: ExUnit.CaptureIO can now be used by tests that run concurrently and we have added “pattern-matching diffing”. To understand the last feature, take this code:

elixir assert %{"status" => 200, "body" => %{"key" => "foo"}} = json_payload

Now imagine that json_payload is a large JSON blob and the "key" inside the "body" did not have value of "foo".

一見それほど重要な改善には感じないのですが、データベースの操作をテストするときにとても役に立ちました。

データベースの操作のばあい、たとえば insert_atupdted_at の値は直接はコントロールできません。 このため完全一致を評価する Kernel.==/2 を使うことはできず Kernel.SpecialForms.=/2 のパタンマッチングを利用することになります。

      {:ok, user} = Accounts.create_user(%{username: "fizz buzz"})

      assert %User{username: "Fizz Buzz"} = Accounts.get_user!(user.id)

1.9 まではマッチングに失敗すると、下記のようにマッチしなかった右辺の値が出力されるだけでした。

     match (=) failed
     code:  assert %User{username: "Fizz Buss"} = Accounts.get_user!(user.id())
     right: %MyApp.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 104, inserted_at: ~N[2020-01-29 11:47:37], updated_at: ~N[2020-01-29 11:47:37], username: "fizz buzz"}
     stacktrace:
       test/my_app/accounts_test.exs:30: (test)

これが 1.10 の改善によって左右のマッチしなかった要素が出力されるようになりました。

     match (=) failed
     code:  assert %User{username: "Fizz Buzz"} = Accounts.get_user!(user.id)
     left:  %MyApp.Accounts.User{username: "Foo Bar"}
     right: %MyApp.Accounts.User{username: "fizz buzz", __meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 85, inserted_at: ~N[2020-01-29 11:19:39], updated_at: ~N[2020-01-29 11:19:39]}
     stacktrace:
       test/my_app/accounts_test.exs:30: (test)

しかもその部分がハイライトされます。

f:id:E_Mattsan:20200129211006p:plain

これまではパタンマッチングでの評価は他の方法が使えないときの苦肉の策のような雰囲気を感じていたのですが、これで心置きなく(?)利用していくことができそうです。