The changes and updates in elixir latest release.
This article comprises of two biggest changes of ExUnit.
- Arguments in the failure report
- Running mix test with failed flag
1. Arguments in the failure report
We mostly do assertions like
assert is_valid_card(card_type, card_number)
with out using any comparison operators like < > <= == >=
inside the unit test cases. Everybody likes being smart. Of course, I do that too.
Personal Experience or impression to write this article:
I have had an experience on the peculiar behaviour 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 the map
with keys of type atom
. Every time I do, the test gets failed. Though I am sending a correct map
, being the keys 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.
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. This 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 moves your 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
endend
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.
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 BasicMathend
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 wrote some test cases to fail on purpose.
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.
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 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.
Some Of other Artilcles You May Be Interested.
Check out the GitHub repository on Killer Elixir Tips
Glad if you can contribute with a ★