Comparing complex data-structures using is_deeply

So far we compared single scalar values to some expected value. What if your function returns an array, a hash, or a multi-dimensional
data structure consisting of lots of arrays and hashes? How can you compare that to some expected data structure?

We have a file called MyTools.pm (In order to let you try the example, the source code of this module is at the end of the article.).
and that module has two public functions given a number $N fibo($N) will return the N-the number in the
Fibonacci series, and the function fibonacci($N) will return
an array reference of the first N element in the series.

As the series is expect to be 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 we can test the fib function easily:

We have the following code in fib.t in the same directory where MyTools.pm is found:

I added a bug to the function on purpose so we can see how failures are reported.

This was the easy case as we had to compare only scalar values.

is_deeply

Testing the fibonacci() function is the more interesting part. It return an ARRAY-reference.
That's the actual-value. The expected value is also an array reference (in square brackets!) and
we use the is_deeply function to compare them.

Here we can see that the test in line 12 called 'fibonacci 5' ha failed. The 3rd element (index 2) of the received
array reference was the first value that differed from the corresponding value in the expected array reference.
is_deeply does not tell you if the rest of the array looked the same or not, but that's usually not that important
and failures, after the first one might be the cascading effect of failures. Usually better to focus on the first error
and then run the test again.

is_deeply on a hash

In the previous example we saw how to test array references using is_deeply. Another interesting example
would be to see how it works when we expect a hash, or a hash reference.
MyTools has an additional function called fetch_data_from_bug_tracking_system that will return
a hash reference based on the number we pass to it. We have a variable called %expected with, well the expected data
structure and we use is_deeply to compare the results.

The first case passed. In the second case the value of key errors was incorrect.
(We expected 6 but we got 9).
In the third case the actual result was missing one of the keys. We expected to have a key called
bugs but we did not have it in the actual result.

Limitations of is_deeply

While it is a very good tool, is_deeply has a number of limitations. It requires the whole data structure to match
exactly. There is no place for any flexibility. For example what if one of the values is a time-stamp that we
would like to disregard or what if we would like to match it with a regular expression?
What if there is an array references where all we case is that each element matches some regular expression,
but we don't even care how many elements are there. For example in the case of the fetch_data_from_bug_tracking_system
function, instead of expecting exact numbers, we might want to expect only the specific keys and "any numerical value".
There is another module called Test::Deep that provides the solution.

MyTools.pm

In order to make it easier for you to test see the above code running, I have included the content of MyTools.pm: