NAME
Test::Deep::Hashbag - A Test::Deep hash comparator ignoring hash keys
VERSION
version 0.002
SYNOPSIS
use strict;
use warnings;
use Test::More;
use Test::Deep;
use Test::Deep::Hashbag;
cmp_deeply(
{
cat => 'meow',
dog => 'bark bark',
fish => 'blub',
},
hashbag(
ignore() => 'meow',
ignore() => re('.*bark.*'),
fish => 'blub',
),
'our animals sound about right',
);
done_testing;
DESCRIPTION
This module provides hashbag and superhashbagof, which are like Test::Deep's bag() and superbagof(), but for hashes.
The idea is it lets you test that a hash has certain values, but you don't know or care what the keys are for those specific values.
EXPORTS
hashbag
cmp_deeply(\%got, hashbag(key => 'val', ignore() => 'val2', ...), $desc);
Takes a list of pairs that are expected to be keys and values. For any keys that aren't ignore(), those keys must exist and have the values provided (this will be checked first).
The remaining values (where the keys are ignore()) will then be checked against the left over values in the input hash.
On failure, the diagnostics will show how many unkeyed items were expected to match, and how many did match in the best possible case. Any keys that matches could not be found for will be printed out, as will any matchers that were not used in this best case.
superhashbagof
cmp_deeply(\%got, superhashbagof(k => 'v', ignore() => 'v2', ...), $desc);
Like hashbag above, but %got may have extra keys/values in it that we don't care about.
NOTES
Diagnostic output variability
With complex matches, the printed information may seem misleading; it can provide different lists of keys or matchers that didn't match on reruns of the test. This indicates that some of the matchers can match multiple keys, and during different test runs they did so in the best case scenario as the matching order is not deterministic.
Performance on large data sets
With larger and larger amounts of values to test, matching will get slower and slower, due to how this module works (testing every expected element against every input). In the future there will be changes to speed up the simple best/worst cases, but there will always be inherent slowness with large amounts of data. Use with caution.
SEE ALSO
THANKS
Thanks to rjbs for pointing out a better algorithm than what I had originally, and to waltman for Graph::MaxFlow which implemented the harder bits of it (until I replaced Graph / Graph::MaxFlow with my own implementation to avoid dependencies :)).
AUTHOR
Matthew Horsfall <wolfsage@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2025 by Fastmail Pty. Ltd.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.