- Arguments in the failure report
- Running mix test with the failed flag
1. Arguments in the failure report
We mostly do assertions like
assert is_valid_card(card_type, card_number)
without using any comparison operators like < > <= == >=
inside the unit test cases. Everybody likes being smart. Of course, I do too.
Personal Experience or impression to write this article:
I have had an experience on the peculiar behavior of maps with two types of keys allowed to write a map
in elixir.
I used a map
with binary
keys and trying to test them over a map with keys of type atom
. Every time I do, the test gets failed. Though I am sending a correct map
, being the keys are of a different type, it gets failed.
It took me a whole day to figure it out. 🌞
I am always trying to debug the code logic instead of arguments that are passed. If the error report has this feature before, I could have saved a day in my life.
Luckily we are having in the latest release.
The Elixir 1.7 versions are smart enough to tell about the arguments given to the function, here is_valid_card(card_type, card_number)
.
As a programmer, I don’t like the documented proof. I always prefer the test_cases
. Well, let’s test
this feature.
Before continuing further, I would like you to know the versions I am using at the moment of writing article.
**Elixir* and Erlang OTP versions*
To test this feature, we will create a project basic_math
and a simple function is_valid_card/2
which is completely an idiot one. This is used to check whether the given card_number
of card_type
is valid or not.
We aren’t much worried to implement the complete logic here. The function, is_valid_card/2
does nothing useful just, it will just judge the length of the card_number
based on the card_type
.
$ mix new basic_math && cd basic_math
The above shell command creates a new Elixir project and changes your current working directory to the basic_math
.
Hope, you all knew the project structure. Well in case if you don’t, check out to My First Project in Elixir.
Open the file lib/basic_math.ex
and put the following lines of code.
#lib/basic_math.ex
defmodule BasicMath do
def is_valid_card(card_type, card_number) do
case card_type do
:debit ->
card_number
|> Integer.to_charlist()
|> length
|> Kernel.==(12)
:credit ->
card_number
|> Integer.to_charlist()
|> length
|> Kernel.==(10)
_ ->
{:error, :invalid_card_type}
end
end
end
After adding the code, the file looks like in the following screenshot…
Quick Docs about the code in basic_math.ex file.
The definition is_valid_card/2
receives two
parameters card_type
and card_number
. We are case matching on card_type
. It matches for two case values :credit & :debit
and I hope you have understood the rest of the code. It is nothing harder than lifting a 1 gram of stone. Nothing like that, I am just kidding.
Unit Test Cases
Now, we will write some unit test cases to test our code.
Before using, test the code.
Open the file test/basic_math_test.exs
and add the following lines of code
Basic Setup
Add the following code
defmodule BasicMathTest do
use ExUnit.Case
import BasicMath
doctest BasicMath
end
Test Cases for debit card
describe "debit_card" do
setup do
{:ok, type: :debit, valid_card: 123456789012, invalid_card: 1234567890}
end
test "valid debit card", %{type: type, valid_card: valid_card} do
assert is_valid_card(type, valid_card)
end
test "in-valid debit card", %{type: type, invalid_card: invalid_card} do
refute is_valid_card(type, invalid_card)
end
end
Test Cases for Credit card
describe "credit_card" do
setup do
{:ok, type: :credit, valid_card: 123456789012, invalid_card: 1234567890}
end
test "valid credit card", %{type: type, valid_card: valid_card} do
assert is_valid_card(type, valid_card)
end
test "in-valid credit card", %{type: type, invalid_card: invalid_card} do
refute is_valid_card(type, invalid_card)
end
end
For the demo purpose, I purposely wrote some test cases to fail.
The overall file looks like in the following screenshot
Under the credit_card section, we are using the same setup data used for debit_card unit test cases which eventually results in failure of the test cases.
So, it will now include the value of each argument in the failure report: Let’s check that.
$ mix test
Run your test cases using the above command. You will see the similar output as in the following screenshot.
mix test … testing the file basic_math.ex
If you observe the above screenshot, Out of four(4), **two(2) **test cases are failed and you can see the arguments passed to the test case in the failure report.
arguments:
#1
:credit
#2
123467890
This kinda failure report is very useful when our function is linked with too many functions. It is hard to debug the fail cause of a unit test case when the function is dependent on many other functions. This is where the arguments play the vital role in debugging the code failures.
It is a great healthy feature. 💚
2. Running mix test with a failed flag 🚩
When you run the command mix test along with a flag--failed, It runs only the test cases that are failed in your previous attempt of mix test.
It means this time the task mix test --failed don’t execute the successful test cases again. So, we can save the time here.
The failed unit test cases are tracked and cached in a very first mix test
We are having totally 4 unit test cases in the file. But, when you added the failed option, it gives out only 2 failed unit test cases.
You can observe that in the following screenshot.
Hope you liked it.
Happy long coding life… :)
Top comments (0)