Test::Snapshot - automate externalising "expected" data
During the ongoing development of graphql-perl, I have found it valuable to generate data structures, and to compare those with expected values. Often, these have been highly detailed rather than a subset, because I wanted to know when anything changed.
When, however, something does validly have to change, it might change quite a few "expected" outputs. If those all need updating manually, that is a lot of repetitive activity. What if the computer could do that instead? What if Perl had "snapshot testing" as used in JavaScript frontend development, most popularly in Jest?
use Test::Snapshot; my $got = function_generating_data(); is_deeply_snapshot $got, 'test description'; # could also be in a subtest
Test::Snapshot automates this! Imagine you have t/subdir/filename.t
, a subtest called "my subtest", and a test you've described as "test description". is_deeply_snapshot
looks for its "expected" data in a file called t/subdir/snapshots/filename_t/my_subtest/test_description
. That data will be read in, and eval
-ed. I considered making a separate is_snapshot
for simple text, but found that Data::Dumper
with the right settings made text so readable that I felt it unnecessary. The data comparison is done using Test::More::is_deeply
.
So far, so good. But what if the data differing is because the "expected" data is now wrong? Easy. Run the tests with environment variable TEST_SNAPSHOT_UPDATE
set to a true value. They'll fail once again, because the expected data still does not match the "got" data. However, when that variable is true and the comparison fails, Test::Snapshot
will also serialise the current "got" data into the appropriate snapshot file automatically. It is safe to have that variable permanently set in development, so long as you check your source-control diffs before committing. You should definitely be doing that anyway!
Nice!
How do I distribute a module with snapshots? Just commit them? (Sounds like a plan...).