Pārlūkot izejas kodu

Fixes #17, adds unit tests.

George S. Baugh 11 gadi atpakaļ
vecāks
revīzija
cb9c20ef44
5 mainītis faili ar 97 papildinājumiem un 5 dzēšanām
  1. 1 0
      Changes
  2. 27 0
      lib/Test/LWP/UserAgent/TestRailMock.pm
  3. 51 2
      lib/Test/Rail/Parser.pm
  4. 17 2
      t/Test-Rail-Parser.t
  5. 1 1
      t/fake.test

+ 1 - 0
Changes

@@ -2,6 +2,7 @@ Revision history for Perl module TestRail::API
 
 0.018 2015-01-29 TEODESIAN
     - Better finding of $HOME in testrail-report and the prove plugin for cross-platform usage
+    - Track elapsed time of tests when run as prove plugin, and report this to testrail
 
 0.017 2015-01-29 TEODESIAN
     - Explicitly import List::Util in TestRail::API, this causes issues on some perls

+ 27 - 0
lib/Test/LWP/UserAgent/TestRailMock.pm

@@ -1182,6 +1182,33 @@ $mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4,
 
 {
 
+$VAR1 = 'index.php?/api/v2/get_results/1';
+$VAR2 = '200';
+$VAR3 = 'OK';
+$VAR4 = bless( {
+                 'connection' => 'close',
+                 'x-powered-by' => 'PHP/5.5.9-1ubuntu4.5',
+                 'client-response-num' => 1,
+                 'date' => 'Tue, 23 Dec 2014 20:02:11 GMT',
+                 'client-peer' => '192.168.122.217:80',
+                 'content-length' => '176',
+                 '::std_case' => {
+                                   'client-date' => 'Client-Date',
+                                   'x-powered-by' => 'X-Powered-By',
+                                   'client-response-num' => 'Client-Response-Num',
+                                   'client-peer' => 'Client-Peer'
+                                 },
+                 'client-date' => 'Tue, 23 Dec 2014 20:02:11 GMT',
+                 'content-type' => 'application/json; charset=utf-8',
+                 'server' => 'Apache/2.4.7 (Ubuntu)'
+               }, 'HTTP::Headers' );
+$VAR5 = '[{"id":8,"test_id":15,"status_id":1,"created_by":1,"created_on":1419364931,"assignedto_id":null,"comment":"REAPER FORCES INBOUND","version":null,"elapsed":"2s","defects":null}]';
+$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));
+
+}
+
+{
+
 $VAR1 = 'index.php?/api/v2/delete_plan/23';
 $VAR2 = '200';
 $VAR3 = 'OK';

+ 51 - 2
lib/Test/Rail/Parser.pm

@@ -9,6 +9,7 @@ use utf8;
 
 use parent qw/TAP::Parser/;
 use Carp qw{cluck confess};
+use POSIX qw{floor};
 
 use TestRail::API;
 use Scalar::Util qw{reftype};
@@ -74,6 +75,8 @@ Get the TAP Parser ready to talk to TestRail, and register a bunch of callbacks
 It is worth noting that if neither step_results or case_per_ok is passed, that the test will be passed if it has no problems of any sort, failed otherwise.
 In both this mode and step_results, the file name of the test is expected to correspond to the test name in TestRail.
 
+This module also attempts to calculate the elapsed time to run each test if it is run by a prove plugin rather than on raw TAP.
+
 =cut
 
 sub new {
@@ -181,6 +184,10 @@ sub new {
     if (defined($self->{'_iterator'}->{'command'}) && reftype($self->{'_iterator'}->{'command'}) eq 'ARRAY' ) {
         $self->{'file'} = $self->{'_iterator'}->{'command'}->[-1];
         print "PROCESSING RESULTS FROM TEST FILE: $self->{'file'}\n";
+        $self->{'track_time'} = 1;
+    } else {
+        #Not running inside of prove in real-time, don't bother with tracking elapsed times.
+        $self->{'track_time'} = 0;
     }
 
     #Make sure the step results field passed exists on the system
@@ -188,6 +195,8 @@ sub new {
 
     $self->{'tr_opts'} = $tropts;
     $self->{'errors'}  = 0;
+    #Start the shot clock
+    $self->{'starttime'} = time();
 
     return $self;
 }
@@ -258,6 +267,11 @@ sub testCallback {
     my $test = $args[0];
     our $self;
 
+    if ( $self->{'track_time'} ) {
+        #Test done.  Record elapsed time.
+        $self->{'tr_opts'}->{'result_options'}->{'elapsed'} = _compute_elapsed($self->{'starttime'},time());
+    }
+
     #Don't do anything if we don't want to map TR case => ok or use step-by-step results
     if ( !($self->{'tr_opts'}->{'step_results'} || $self->{'tr_opts'}->{'case_per_ok'}) ) {
         print "Neither step_results of case_per_ok set.  No action to be taken, except on a whole test basis.\n" if $self->{'tr_opts'}->{'debug'};
@@ -332,6 +346,8 @@ sub testCallback {
     my $custom_options = $self->{'tr_opts'}->{'result_custom_options'};
 
     _set_result($run_id,$test_name,$status,$notes,$options,$custom_options);
+    #Re-start the shot clock
+    $self->{'starttime'} = time();
 
     #Blank out test description in anticipation of next test
     # also blank out notes
@@ -350,9 +366,14 @@ Otherwise, upload the overall results of the test to TestRail.
 sub EOFCallback {
     our $self;
 
+    if ( $self->{'track_time'} ) {
+        #Test done.  Record elapsed time.
+        $self->{'tr_opts'}->{'result_options'}->{'elapsed'} = _compute_elapsed($self->{'starttime'},time());
+    }
+
     if (!(!$self->{'tr_opts'}->{'step_results'} xor $self->{'tr_opts'}->{'case_per_ok'})) {
         print "Nothing left to do.\n";
-        undef $self->{'tr_opts'};
+        undef $self->{'tr_opts'} unless $self->{'tr_opts'}->{'debug'};
         return 1;
     }
 
@@ -379,7 +400,7 @@ sub EOFCallback {
     print "Setting results...\n";
     my $cres = _set_result($run_id,$test_name,$status,$notes,$options,$custom_options);
 
-    undef $self->{'tr_opts'};
+    undef $self->{'tr_opts'} unless $self->{'tr_opts'}->{'debug'};
 
     return $cres;
 }
@@ -389,6 +410,8 @@ sub _set_result {
     our $self;
     my $tc;
 
+    print "Test elapsed: ".$options->{'elapsed'}."\n" if $options->{'elapsed'};
+
     print "Attempting to find case by title '".$test_name."'...\n";
     $tc = $self->{'tr_opts'}->{'testrail'}->getTestByName($run_id,$test_name);
     if (!defined($tc) || (reftype($tc) || 'undef') ne 'HASH') {
@@ -415,6 +438,32 @@ sub _set_result {
 
 }
 
+#Compute the expected testrail date interval from 2 unix timestamps.
+sub _compute_elapsed {
+    my ($begin,$end)  = @_;
+    my $secs_elapsed  = $end - $begin;
+    my $mins_elapsed  = floor($secs_elapsed / 60);
+    my $secs_remain   = $secs_elapsed % 60;
+    my $hours_elapsed = floor($mins_elapsed / 60);
+    my $mins_remain   = $mins_elapsed % 60;
+
+    my $datestr = "";
+
+    #You have bigger problems if your test takes days
+    if ($hours_elapsed) {
+        $datestr .= "$hours_elapsed"."h $mins_remain"."m";
+    } else {
+        $datestr .= "$mins_elapsed"."m";
+    }
+    if ($mins_elapsed) {
+        $datestr .= " $secs_remain"."s";
+    } else {
+        $datestr .= " $secs_elapsed"."s";
+    }
+    undef $datestr if $datestr eq "0m 0s";
+    return $datestr;
+}
+
 1;
 
 __END__

+ 17 - 2
t/Test-Rail-Parser.t

@@ -3,10 +3,11 @@
 use strict;
 use warnings;
 
+use Scalar::Util qw{reftype};
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 use Test::Rail::Parser;
-use Test::More 'tests' => 21;
+use Test::More 'tests' => 26;
 use Test::Fatal qw{exception};
 
 #Same song and dance as in TestRail-API.t
@@ -18,8 +19,8 @@ my $is_mock = (!$apiurl && !$login && !$pw);
 ($apiurl,$login,$pw) = ('http://testrail.local','teodesian@cpan.org','fake') if $is_mock;
 my ($debug,$browser);
 
+$debug = 1;
 if ($is_mock) {
-    $debug = 1;
     $browser = $Test::LWP::UserAgent::TestRailMock::mockObject;
 }
 
@@ -81,6 +82,20 @@ if (!$res) {
     is($tap->{'errors'},0,"No errors encountered uploading case results");
 }
 
+#Check that time run is being uploaded
+my $timeResults = $tap->{'tr_opts'}->{'testrail'}->getTestResults(1);
+if ( ( reftype($timeResults) || 'undef') eq 'ARRAY') {
+    is( $timeResults->[0]->{'elapsed'}, '2s', "Plugin correctly sets elapsed time");
+} else {
+    fail("Could not get test results to check elapsed time!");
+}
+
+#Check the time formatting routine.
+is(Test::Rail::Parser::_compute_elapsed(0,0),undef,"Elapsed computation correct at second boundary");
+is(Test::Rail::Parser::_compute_elapsed(0,61),'1m 1s',"Elapsed computation correct at minute boundary");
+is(Test::Rail::Parser::_compute_elapsed(0,3661),'1h 1m 1s',"Elapsed computation correct at hour boundary");
+is(Test::Rail::Parser::_compute_elapsed(0,86461),'24h 1m 1s',"Elapsed computation correct at day boundary");
+
 #Time for non case_per_ok mode
 undef $tap;
 $res = exception {

+ 1 - 1
t/fake.test

@@ -4,7 +4,7 @@ use strict;
 use warnings;
 
 use Test::More 'tests' => 2;
-
+sleep(2);
 pass('STORAGE TANKS SEARED');
 note('whee');
 fail('NOT SO SEARED AFTER ARR');