App-Test-Generator
view release on metacpan or search on metacpan
t/PodExampleExtractor_unit.t view on Meta::CPAN
=head2 new
use Foo;
=cut
1;
PM
my $ex = App::Test::Generator::PodExampleExtractor->new(file => $pm);
my $res = $ex->extract();
my @use_foo = grep { $_->{code} eq 'use Foo;' } @$res;
is(scalar @use_foo, 1, 'duplicate code block appears only once');
};
# ==================================================================
# Label assignment
# ==================================================================
subtest 'extract() assigns numbered labels within each section' => sub {
my $pm = _tmp_pm(<<'PM');
package Foo;
=head2 greet
my $x = greet('A'); # returns 'Hello, A!'
my $y = greet('B'); # => 'Hello, B!'
=cut
sub greet { "Hello, $_[1]!" }
1;
PM
my $ex = App::Test::Generator::PodExampleExtractor->new(file => $pm);
my $res = $ex->extract();
my @greet = grep { $_->{section} eq 'greet' } @$res;
ok(@greet >= 2, 'two greet examples');
like($greet[0]{label}, qr/example 1/, 'first label ends in 1');
like($greet[1]{label}, qr/example 2/, 'second label ends in 2');
};
# ==================================================================
# Real module: Sample::Module
# ==================================================================
subtest 'extract() works on Sample::Module and finds annotated examples' => sub {
my $path = 'lib/App/Test/Generator/Sample/Module.pm';
unless(-f $path) {
plan skip_all => "Sample::Module not present ($path)";
}
my $ex = App::Test::Generator::PodExampleExtractor->new(file => $path);
my $res = $ex->extract();
ok(scalar @$res > 0, 'examples found in Sample::Module');
my @ann = grep { defined $_->{expected} } @$res;
ok(@ann >= 2, 'at least two annotated examples found');
my ($vs) = grep { $_->{code} =~ /validate_score.*75\.5/ } @ann;
ok(defined $vs, 'validate_score(75.5) example found');
is($vs->{expected}, "'Pass'", "expected value is 'Pass'");
};
# ==================================================================
# Shell-command filtering (_looks_like_perl)
# ==================================================================
subtest 'extract() skips verbatim blocks containing only shell commands' => sub {
my $pm = _tmp_pm(<<'PM');
package Foo;
=head1 SYNOPSIS
fuzz-harness-generator -r schemas/foo.yml
extract-schemas lib/Foo.pm && fuzz-harness-generator -r schemas/greet.yml
use Foo;
=cut
1;
PM
my $ex = App::Test::Generator::PodExampleExtractor->new(file => $pm);
my $res = $ex->extract();
ok(!grep({ $_->{code} =~ /fuzz-harness-generator|extract-schemas/ } @$res),
'shell-command blocks are not extracted');
my @perl = grep { $_->{code} =~ /use Foo/ } @$res;
is(scalar @perl, 1, 'Perl code block is still extracted');
};
subtest 'pod-example-tester neutralizes system() calls in generated output' => sub {
my $pm = _tmp_pm(<<'PM');
package Bar;
=head1 SYNOPSIS
my $result = Bar->run();
system("rm -rf /");
=cut
sub run { 1 }
1;
PM
my $out = File::Temp->new(SUFFIX => '.t', UNLINK => 1);
system($^X, '-Ilib', 'bin/pod-example-tester', '--output', "$out", $pm) == 0
or plan skip_all => 'pod-example-tester not runnable';
my $generated = do { local $/; open my $fh, '<', "$out" or die $!; <$fh> };
unlike($generated, qr/^\s+system\s*\(/m, 'no executable system() statement in generated file');
like($generated, qr/note\(.*skipped shell call/i, 'system() replaced with note()');
};
subtest '_looks_like_perl keeps blocks with sigils, keywords, :: and ->' => sub {
my $pm = _tmp_pm(<<'PM');
package Foo;
=head1 SYNOPSIS
my $obj = Foo->new();
prove -l t/foo.t
$obj->method();
=cut
1;
PM
my $ex = App::Test::Generator::PodExampleExtractor->new(file => $pm);
my $res = $ex->extract();
ok(!grep({ $_->{code} =~ /prove/ } @$res), 'bare "prove" command is skipped');
is(scalar(grep { $_->{code} =~ /Foo->new/ || $_->{code} =~ /\$obj/ } @$res),
2, 'two Perl blocks retained');
};
done_testing();
( run in 0.455 second using v1.01-cache-2.11-cpan-6aa56a78535 )