GoodData

Named or positional arguments ?

both with Sub::Params

    use Sub::Params;

    sub foo {
        my %args = Sub::Params::named_or_positional_arguments (
            args => \@_,
            names => [qw[ first second ]],
        );

        return $args{first} + $args{second};
    }

    say foo (1, 2);
    # 3
    say foo (first => 1, second => 2);
    # 3

Shared examples

    use Shared::Examples::Net::Amazon::S3::Client (
        qw[ expect_client_object_delete ],
    );

    use Shared::Examples::Net::Amazon::S3::Error (
        qw[ fixture_error_access_denied ],
    );

    expect_client_object_delete 'delete object' => (
        with_bucket             => 'some-bucket',
        with_key                => 'some-key',
        expect_request          => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' },
        expect_data             => bool (1),
    );

    expect_client_object_delete 'error access denied' => (
        with_bucket             => 'some-bucket',
        with_key                => 'some-key',
        fixture_error_access_denied,
        expect_request          => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' },
        throws                  => qr/^AccessDenied: Access denied error message/,
    );