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
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
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
I totally respect your position too.
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
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.







