App-Cmd

 view release on metacpan or  search on metacpan

lib/App/Cmd/Tester.pm  view on Meta::CPAN

sub test_app {
  my ($class, $app, $argv) = @_;

  local $App::Cmd::_bad = 0;

  $app = $app->new unless ref($app) or $app->isa('App::Cmd::Simple');

  my $result = $class->_run_with_capture($app, $argv);

  my $error = $result->{error};

  my $exit_code = defined $error ? ((0+$!)||-1) : 0;

  if ($error and eval { $error->isa('App::Cmd::Tester::Exited') }) {
    $exit_code = $$error;
  }

  $exit_code =1 if $App::Cmd::_bad && ! $exit_code;

  $class->result_class->new({
    app    => $app,
    exit_code => $exit_code,
    %$result,
  });
}

sub _run_with_capture {
  my ($class, $app, $argv) = @_;

  require IO::TieCombine;
  my $hub = IO::TieCombine->new;

  my $stdout = tie local *STDOUT, $hub, 'stdout';
  my $stderr = tie local *STDERR, $hub, 'stderr';

  my $run_rv;

  my $ok = eval {
    local $TEST_IN_PROGRESS = 1;
    local @ARGV = @$argv;
    $run_rv = $app->run;
    1;
  };

  my $error = $ok ? undef : $@;

  return {
    stdout => $hub->slot_contents('stdout'),
    stderr => $hub->slot_contents('stderr'),
    output => $hub->combined_contents,
    error  => $error,
    run_rv => $run_rv,
  };
}

{
  package App::Cmd::Tester::Result 0.336;

  sub new {
    my ($class, $arg) = @_;
    bless $arg => $class;
  }

  for my $attr (qw(app stdout stderr output error run_rv exit_code)) {
    Sub::Install::install_sub({
      code => sub { $_[0]->{$attr} },
      as   => $attr,
    });
  }
}

{
  package App::Cmd::Tester::Exited 0.336;

  sub throw {
    my ($class, $code) = @_;
    $code = 0 unless defined $code;
    my $self = (bless \$code => $class);
    die $self;
  }
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

App::Cmd::Tester - for capturing the result of running an app

=head1 VERSION

version 0.336

=head1 SYNOPSIS

  use Test::More tests => 4;
  use App::Cmd::Tester;

  use YourApp;

  my $result = test_app(YourApp => [ qw(command --opt value) ]);

  like($result->stdout, qr/expected output/, 'printed what we expected');

  is($result->stderr, '', 'nothing sent to sderr');

  is($result->error, undef, 'threw no exceptions');

  my $result = test_app(YourApp => [ qw(command --opt value --quiet) ]);

  is($result->output, '', 'absolutely no output with --quiet');

=head1 DESCRIPTION

One of the reasons that user-executed programs are so often poorly tested is
that they are hard to test.  App::Cmd::Tester is one of the tools App-Cmd
provides to help make it easy to test App::Cmd-based programs.

It provides one routine: test_app.

=head1 PERL VERSION

This library should run on perls released even a long time ago.  It should
work on any version of perl released in the last five years.

Although it may work on older versions of perl, no guarantee is made that the
minimum required version will not be increased.  The version may be increased
for any reason, and there is no promise that patches will be accepted to
lower the minimum required perl.

=head1 METHODS

=head2 test_app

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.874 second using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )