Perl - статьи
ba2f5a3f

Test-coverage-report


#!/usr/bin/perl

#=============================================================================== # REVISION: $Id$ # DESCRIPTION: Build & display test coverage report # AUTHOR: Alexander Simakov, <xdr [dot] box [at] Gmail>

# http://alexander-simakov.blogspot.com/ # LICENSE: Public domain #===============================================================================

use strict; use warnings;

our $VERSION = qw($Revision$) [1];

use Readonly; use English qw( -no_match_vars ); use Getopt::Long 2.24 qw(:config no_auto_abbrev no_ignore_case); use Pod::Usage; use IO::Prompt; use File::Temp qw(tempdir); use File::Basename; use Carp;

#use Smart::Comments;

Readonly my $DEFAULT_PROVE_CMD => '/usr/bin/prove'; Readonly my $DEFAULT_PROVE_ARGS => q{};

Readonly my $DEFAULT_COVER_CMD => '/usr/bin/cover'; ## no critic (RequireInterpolationOfMetachars) Readonly my $DEFAULT_COVER_ARGS => q{-ignore_re '[.]t$'}; ## use critic

Readonly my $DEFAULT_BROWSER_CMD => q{}; Readonly my $DEFAULT_BROWSER_ARGS => q{};

sub get_options { my $options = { 'prove-cmd' => $DEFAULT_PROVE_CMD, 'prove-args' => $DEFAULT_PROVE_ARGS, 'cover-cmd' => $DEFAULT_COVER_CMD, 'cover-args' => $DEFAULT_COVER_ARGS, 'browser-cmd' => $DEFAULT_BROWSER_CMD, 'browser-args' => $DEFAULT_BROWSER_ARGS, };

my $options_okay = GetOptions( $options, 'input-file|f=s', # Input .t or .pm file 'prove-cmd|p=s', # Which prove command to use 'prove-args|P=s', # prove args 'cover-cmd|c=s', # Which cover command 'cover-args|C=s', # cover args 'browser-cmd|b=s', # Which browser to use 'browser-args|B=s', # Browser args 'output-dir|d=s', # Output directory 'help|?', # Show brief help message 'man', # Show full documentation );

# More meaningful names for pod2usage's -verbose parameter Readonly my $SHOW_USAGE_ONLY => 0; Readonly my $SHOW_BRIEF_HELP_MESSAGE => 1; Readonly my $SHOW_FULL_MANUAL => 2;



# Show appropriate help message if ( !$options_okay ) { pod2usage( -exitval => 2, -verbose => $SHOW_USAGE_ONLY ); }


if ( $options->{'help'} ) { pod2usage( -exitval => 0, -verbose => $SHOW_BRIEF_HELP_MESSAGE ); }

if ( $options->{'man'} ) { pod2usage( -exitval => 0, -verbose => $SHOW_FULL_MANUAL ); }

# Check required options foreach my $option (qw( input-file browser-cmd prove-cmd cover-cmd )) { if ( !$options->{$option} ) { pod2usage( -message => "Option $option is required", -exitval => 2, -verbose => $SHOW_USAGE_ONLY, ); } }

### options: $options return $options; }

sub create_tmp_dir { my $output_dir = shift; my $input_file = shift;

my $basename = basename( $input_file, qw(.pm .t) ); ### basename: $basename

my $tmp_dir; if ($output_dir) { $tmp_dir = tempdir( "$basename-XXXX", DIR => $output_dir, CLEANUP => 0, ); } else { $tmp_dir = tempdir( "$basename-XXXX", TMPDIR => 1, CLEANUP => 0, ); } ### tmp_dir: $tmp_dir

return $tmp_dir; }

sub enable_coverage_report { my $output_dir = shift;

$ENV{'HARNESS_PERL_SWITCHES'} = "-MDevel::Cover=-db,$output_dir";

return; }

sub prove { my $input_file = shift; my $prove_cmd = shift; my $prove_args = shift;

system "$prove_cmd $input_file $prove_args";

return if $CHILD_ERROR == 0; croak 'Cannot prove the test'; }

sub generate_coverage_report { my $output_dir = shift; my $cover_cmd = shift; my $cover_args = shift;

system "$cover_cmd $cover_args $output_dir";

return if $CHILD_ERROR == 0; croak 'Cannot generate coverage report'; }

sub open_browser { my $url = shift; my $browser_cmd = shift; my $browser_args = shift;

system "$browser_cmd $browser_args $url";

return if $CHILD_ERROR == 0; croak 'Cannot open browser'; }

sub cleanup_dir { my $dir = shift;

system "rm -frv '$dir'";

return; }

sub confirm_cleanup { my $output_dir = shift;

my $msg = "Coverage report is generated in '$output_dir'. " . 'Press \'Y\' (default) to cleanup this directory or \'N\' ' . 'if you want to keep it.';

my $answer = prompt( $msg, -default => 'Y', -YN, -one_char );



if ( $answer eq 'Y' ) { cleanup_dir($output_dir); }

return; }

sub build_coverage_report { my $options = shift;

my $tmp_dir = create_tmp_dir( $options->{'output-dir'}, $options->{'input-file'} );

enable_coverage_report($tmp_dir);

eval { prove( $options->{'input-file'}, $options->{'prove-cmd'}, $options->{'prove-args'}, );

generate_coverage_report( $tmp_dir, $options->{'cover-cmd'}, $options->{'cover-args'}, );

open_browser( "$tmp_dir/coverage.html", $options->{'browser-cmd'}, $options->{'browser-args'}, ); };

if ($EVAL_ERROR) { print "$EVAL_ERROR\n"; cleanup_dir($tmp_dir);

exit 1; }

confirm_cleanup($tmp_dir);

return; }

sub main { my $options = get_options();

build_coverage_report($options);

return; }

main();

__END__ =head1 NAME test-coverage-report.pl - Build & display test coverage report =head1 SYNOPSIS test-coverage-report.pl [options] &#xa0;Options: &#xa0;&#xa0;&#xa0;--input-file|-f Input .t or .pm file &#xa0;&#xa0;&#xa0;--prove-cmd|- p Which prove command to use &#xa0;&#xa0;&#xa0;--prove-args|-P prove args &#xa0;&#xa0;&#xa0;--cover-cmd|-c Which cover command &#xa0;&#xa0;&#xa0;--cover-args|-C cover args &#xa0;&#xa0;&#xa0;--browser-cmd|-b Which browser to use &#xa0;&#xa0;&#xa0;--browser-args|-B Browser args &#xa0;&#xa0;&#xa0;--output-dir|-d Output directory &#xa0;&#xa0;&#xa0;--help|-? Show brief help message &#xa0;&#xa0;&#xa0;--man Show full documentation =head1 DESCRIPTION Run tests, build coverage report and open web-browser. =cut


Содержание раздела