gavid

gavid

Difference between using assert and pattern matching in unit test

I came across the following code when browsing the FireZone GitHub repository:

  use ExUnit.Case, async: true

  alias FzVpn.Interface
  alias FzVpn.Server

  test "delete interface" do
    name = "wg-delete"
    :ok = Interface.set(name, %{})

    assert :ok == Interface.delete(name)
  end

If I understand correctly, the line :ok = Interface.set(name, %{}) will raise a MatchError if Interface.set(name, %{}) doesn’t return :ok. Why not simply use an assert statement, as is done in the very next line?

Most Liked

sodapopcan

sodapopcan

I think the question is more “why bother with the :ok = ?” I know there was some discussion about that around here recent-ish-ly but I’m sorry I can’t find it. It does bring the error (that should never happen) up to the test code which is maybe convenient? It also does indicate, as already pointed out, that that line can’t (or at least shouldn’t ever) fail. Maybe there is something more obvious I’m missing.

Otherwise, I would caution against adding asserts to lines that you aren’t the explicit subject under test as it makes things less clear. IE, in this case, Interface.set is not what is being tested, it’s just part of the setup. You could otherwise technically assert or refute every line single line!

ityonemo

ityonemo

Ps you can assert on matches too.

I take a different take. I encourage asserting as much as possible because asserts give better error messages than pattern matches. Probably don’t assert something that is a basically unfailable primitive on another library (for example assert :ok = MyPubSub.subscribe(...) is silly, but if it’s like assert {:ok, inserted} = Db.insert(...) Yeah go ahead and do it even if it’s part of your setup.

ityonemo

ityonemo

I totally respect your position too.

hassanRsiddiqi

hassanRsiddiqi

test “delete interface” do

As per the test title, the author is currently testing the delete interface, So when writing a test we should only focus on what this test suppose to do, So the key is to make the test simple and more focused on the current scenario. So readers can understand the test better.
that is why he has assertion only on delete

stevensonmt

stevensonmt

what about

  use ExUnit.Case, async: true

  alias FzVpn.Interface
  alias FzVpn.Server

  test "delete interface" do
    name = "wg-delete"
    with :ok <- Interface.set(name, %{}) do
      assert :ok == Interface.delete(name)
    else
       _ -> raise RuntimeError "test failed because of setup rather than on delete"
    end
  end

or something similar? This way you get a meaningful error if there’s an issue with the setup step, but your test is still focused.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement