testing beginner

How to test subroutine output with is_deeply in Perl?

Question

How to test subroutine output with is_deeply in Perl?

When testing Perl subroutines that return complex data structures, is_deeply from the Test::More module is essential. Unlike is(), which compares scalar values or references by address, is_deeply performs a recursive comparison of the entire data structure, making it ideal for arrays, hashes, and nested references.

Understanding is_deeply

is_deeply checks two referenced data structures for equivalence by comparing each element, recursively. It works with complex nested data making your tests robust and reliable.

Key Points and Pitfalls

  • References vs. Values: Using is() to compare references only compares memory addresses, so it usually fails for distinct structures with the same content.
  • Context: Always ensure the subroutine's return value is captured in the appropriate context (scalar vs. list) matching your expected data structure.
  • Order Matters: Arrays are order-sensitive, hashes are order-insensitive but value-sensitive.
  • Core Module: Test::More has been core since Perl 5.6, so no external installs needed.

Corrected Example: Testing Output with is_deeply

This example shows a subroutine returning a hash reference, tested with is_deeply. The second test using is() is commented out because it always fails for distinct references and would break testing flow.

use strict;
use warnings;
use Test::More tests => 1;

# Subroutine returning a complex hashref
sub get_user_info {
    my ($user_id) = @_;
    return {
        id    => $user_id,
        name  => 'Alice',
        roles => [ 'admin', 'editor' ],
    };
}

my $expected = {
    id    => 42,
    name  => 'Alice',
    roles => [ 'admin', 'editor' ],
};

my $actual = get_user_info(42);

is_deeply($actual, $expected, 'get_user_info returns expected user info');

# Note: The following test is commented out because it fails
# is($actual, $expected, 'is() fails because references differ');

Summary

Use is_deeply to confirm complex data structures returned by subroutines match expected values recursively. Avoid using is() on references to data structures as it only compares memory addresses, not content. This approach leads to more accurate and maintainable test suites in Perl.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 58ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
1..1
ok 1 - get_user_info returns expected user info
STDERR
(empty)

Was this helpful?

Related Questions