Test-Effects

 view release on metacpan or  search on metacpan

lib/Test/Effects.pm  view on Meta::CPAN

# Test all trapped info, as requested...
sub effects_ok (&;+$) {
    my ($block, $expected, $desc) = @_;
    my $expected_ref = ref $expected;

    # Handle case where hash is missing, but description isn't...
    if (@_ == 2 && !$expected_ref) {
        $desc     = "$expected";
        $expected = undef;
    }

    # Expectations are passed in a hash...
    $expected //= {};
    if (ref($expected) ne 'HASH') {
        _croak 'Second argument to effects_ok() must be hash or hash reference, not '
             . lc(ref($expected) || 'scalar value');
    }

    # If there's a timing request, the value has to make sense...
    my $timing;
    if (exists $expected->{'timing'}) {
        my $spec = $expected->{'timing'};
        my $valid_time =  ref($spec) =~ m{ \A (?: HASH | ARRAY ) \Z}xms
                      || !ref($spec) && looks_like_number($spec);
        if (!$valid_time) {
            _croak("Invalid timing specification: timing => '$spec'");
        }
    }

    # Get lexical hints...
    my %lexical_hint = %{ (caller 0)[10] // {} };

    # Fill in default tests, unless requested not to...
    my $is_only
        = exists $expected->{'ONLY'} ? $expected->{'ONLY'}
        :                              $lexical_hint{'Test::Effects::ONLY'};

    # Time the test, if requested
    my $timed_test
        = exists $expected->{'TIME'} ? $expected->{'TIME'}
        :                              $lexical_hint{'Test::Effects::TIME'};

    if (!$is_only) {
        my $warn = $expected->{'warn'};
        $expected = {
            %NULL_VALUE_FOR,
            'stderr' => (ref $warn eq 'ARRAY' ? join(q{}, @{$warn}) : $warn),
            %{$expected},
        };
    }

    # Correct common mispecifications...
    for my $option (keys %BAD_NULL_VALUE_FOR) {
        next if !exists $expected->{$option};
        if (match( $expected->{$option}, $BAD_NULL_VALUE_FOR{$option} )) {
            $expected->{$option} = $NULL_VALUE_FOR{$option};
        }
    }

    # Ensure there's a description...
    $desc //= sprintf "Testing effects_ok() at %s line %d", (caller)[1,2];

    # Are we echoing this test???
    my $is_terse
        = exists $expected->{'VERBOSE'} ? !$expected->{'VERBOSE'}
        :                                 !$lexical_hint{'Test::Effects::VERBOSE'};

    # Show the description...
    my $preview_desc = !$is_terse || exists $expected->{'timing'};
    if ($preview_desc) {
        note '_' x (3 + length $desc);
        note exists $expected->{'timing'}
                ? "$desc (being timed)..."
                : "$desc...";
    }

    # Redirect test output, so we can retrospectively de-terse on errors...
    my $tests_output;
    for my $builder (Test::Builder->new()) {
        $builder->output(\$tests_output);
        $builder->failure_output(\$tests_output);
        $builder->todo_output(\$tests_output);
    }

    # Preview description under terse too, in case of failures...
    if (!$preview_desc) {
        note '_' x (3 + length $desc);
        note "$desc...";
    }

    # Are we WITHOUT any modules in this test???
    my @real_INC = @INC;
    local @INC = @INC;
    local %INC = %INC;
    if (exists $expected->{'WITHOUT'}) {
        my $without_list = $expected->{'WITHOUT'};

        # Normalize list...
        if (ref $without_list ne 'ARRAY') {
            $without_list = [ $without_list ];
        }

        # Translate list to filepaths...
        for my $module_name ( @{$without_list} ) {
            # Classify the argument...
            my $is_pattern = ref $module_name eq 'Regexp';
            my $is_libpath = $module_name =~ m{/};

            # Modules get translated to paths...
            if (!$is_libpath) {
                if (not $module_name =~ s{::}{/}gxms) {
                    diag "WARNING: ambiguous WITHOUT => "
                       . ($is_pattern ? "qr{$module_name}" : "'$module_name'")
                       . "\ntreated as module name (not library path)"
                       . "\n(use "
                       . ($is_pattern ? "qr{::$module_name}" : "'::$module_name'")
                       . " or "
                       . ($is_pattern ? "qr{$module_name/}" : "'$module_name/'")
                       . " to silence this warning)";
                }
                if (!$is_pattern) {



( run in 2.535 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )