Using 'like' to test without exact values

When testing a function, the best is if we can test that the function returns exactly what we expected.
Unfortunately this is not always possible or worth the effort. For example, what if part of the return value
is a timestamp that will be different every time we run the script.
We can mock the time to pretend it is some other time
of the year, but even that might not work out. If we get a newer machine, the process might run faster
and by the returned time might not be exactly the same.

Timestamp

If we call this subroutine it will return This page was last updated at 2014-09-23T04:43:44.
But it will return it only once at that exact second. (Wow, was I really awake at 4 am, or is this
giving me the time in London?)

Disregard the timestamp

So how can we test if the subroutine returns the correct value?
(For the purpose of this example, I've included the last_update function in the test script,
but in normal situation that would be in a real module.)

We can use a regular expression to check if the returned string contains the text we expect and we can
just disregard the time. We can use the ok() function to check and report if the match was correct,
but as we have already learned, there are better tools, that will be especially interesting if the test
actually fails.

Using like

The like function provided by Test::More,
accepts 3 parameters. The actual returned value. A regular expression created using qr,
and the optional name of the test. It will apply regex matching between the first two parameters.
It will print ok if there is a match and not ok with some details when there is no match.
So we can rewrite the above test case as follows:

However there is another issue here. In this test we have basically disregarded anything that got returned after the
word 'at'. The function might not return a timestamp, or it might return some 4-letter words after the 'at' and
we won't catch it with this test.

The middle-ground between exact value that will never succeed and matching only the prefix that can succeed even when
the code behind it is broken, is to use a more specific regex:

like( last_update(),
qr/^This page was last updated at \d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d$/, 'last_update full match');

In this case we only expect a certain format of the timestamp, but we don't care about the specific date.

The first two test-units have printed ok as they both have disregarded the time-stamp.
The 3rd test will fail and print an interesting diagnosis. It will print the actual string we have
passed to like() as the first parameter and the regex we were trying to match.

Conclusion

If you cannot check the exact return value, you don't have to totally disregard part of the result.
You can create a regex and use like to check if the return looks similar to what we expected.