Browse Source

Fix #76: allow tests to signal parser to mark as other status

George S. Baugh 9 years ago
parent
commit
02234225fa
3 changed files with 60 additions and 9 deletions
  1. 30 0
      lib/Test/Rail/Parser.pm
  2. 7 7
      lib/TestRail/API.pm
  3. 23 2
      t/Test-Rail-Parser.t

+ 30 - 0
lib/Test/Rail/Parser.pm

@@ -102,6 +102,25 @@ If you are not in case_per_ok mode, the global status of the case will be set ac
 
 
 Step results will always be whatever status is relevant to the particular step.
 Step results will always be whatever status is relevant to the particular step.
 
 
+=head1 TAP Extensions
+
+=head2 Forcing status reported
+
+A line that begins like so:
+
+% mark_status=
+
+Will allow you to force the status of a test case to whatever is on the RHS of the = expression.
+
+Example (force test to retest in event of tool failure):
+
+    my $failed = do_something_possibly_causing_tool_failure();
+    print "% mark_status=retest" if $failed;
+
+Bogus statuses will cluck, but otherwise be ignored.  Valid statuses are any of the required internal names in your TestRail install (see above).
+
+Multiple instances of this will ignore all but the latest valid status.
+
 =cut
 =cut
 
 
 sub new {
 sub new {
@@ -308,6 +327,14 @@ sub unknownCallback {
     my $line = $test->as_string;
     my $line = $test->as_string;
     $self->{'raw_output'} .= "$line\n";
     $self->{'raw_output'} .= "$line\n";
 
 
+    #Unofficial "Extensions" to TAP
+    my ($status_override) = $line =~ m/^% mark_status=([a-z|_]*)/;
+    if ($status_override) {
+        cluck "Unknown status override" unless defined $self->{'tr_opts'}->{$status_override}->{'id'};
+        $self->{'global_status'} = $self->{'tr_opts'}->{$status_override}->{'id'} if $self->{'tr_opts'}->{$status_override};
+        print "# Overriding status to $status_override (".$self->{'global_status'}.")...\n" if $self->{'global_status'};
+    }
+
     #XXX I'd love to just rely on the 'name' attr in App::Prove::State::Result::Test, but...
     #XXX I'd love to just rely on the 'name' attr in App::Prove::State::Result::Test, but...
     #try to pick out the filename if we are running this on TAP in files, where App::Prove is uninvolved
     #try to pick out the filename if we are running this on TAP in files, where App::Prove is uninvolved
     my $file = TestRail::Utils::getFilenameFromTapLine($line);
     my $file = TestRail::Utils::getFilenameFromTapLine($line);
@@ -487,6 +514,9 @@ sub EOFCallback {
     $status = $self->{'tr_opts'}->{'todo_pass'}->{'id'} if $self->todo_passed() && !$self->failed() && $self->is_good_plan(); #If no fails, but a TODO pass, mark as TODO PASS
     $status = $self->{'tr_opts'}->{'todo_pass'}->{'id'} if $self->todo_passed() && !$self->failed() && $self->is_good_plan(); #If no fails, but a TODO pass, mark as TODO PASS
     $status = $self->{'tr_opts'}->{'skip'}->{'id'}      if $self->skip_all(); #Skip all, whee
     $status = $self->{'tr_opts'}->{'skip'}->{'id'}      if $self->skip_all(); #Skip all, whee
 
 
+    #Global status override
+    $status = $self->{'global_status'} if $self->{'global_status'};
+
     #Optional args
     #Optional args
     my $notes          = $self->{'tr_opts'}->{'test_notes'};
     my $notes          = $self->{'tr_opts'}->{'test_notes'};
     $notes = $self->{'raw_output'};
     $notes = $self->{'raw_output'};

+ 7 - 7
lib/TestRail/API.pm

@@ -173,13 +173,13 @@ sub _doRequest {
     my $response = $self->{'browser'}->request($req);
     my $response = $self->{'browser'}->request($req);
 
 
     #Uncomment to generate mocks
     #Uncomment to generate mocks
-    use Data::Dumper;
-    open(my $fh, '>>', 'mock.out');
-    print $fh "{\n\n";
-    print $fh Dumper($path,'200','OK',$response->headers,$response->content);
-    print $fh '$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));';
-    print $fh "\n\n}\n\n";
-    close $fh;
+    #use Data::Dumper;
+    #open(my $fh, '>>', 'mock.out');
+    #print $fh "{\n\n";
+    #print $fh Dumper($path,'200','OK',$response->headers,$response->content);
+    #print $fh '$mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));';
+    #print $fh "\n\n}\n\n";
+    #close $fh;
 
 
     return $response if !defined($response); #worst case
     return $response if !defined($response); #worst case
     if ($response->code == 403) {
     if ($response->code == 403) {

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

@@ -10,7 +10,7 @@ use Scalar::Util qw{reftype};
 use TestRail::API;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 use Test::LWP::UserAgent::TestRailMock;
 use Test::Rail::Parser;
 use Test::Rail::Parser;
-use Test::More 'tests' => 89;
+use Test::More 'tests' => 93;
 use Test::Fatal qw{exception};
 use Test::Fatal qw{exception};
 
 
 #Same song and dance as in TestRail-API.t
 #Same song and dance as in TestRail-API.t
@@ -336,7 +336,7 @@ $fcontents = "
 todo_pass.test ..
 todo_pass.test ..
 1..2
 1..2
 ok 1 - STORAGE TANKS SEARED #TODO todo pass
 ok 1 - STORAGE TANKS SEARED #TODO todo pass
-#goo
+# goo
 ";
 ";
 undef $opts->{'source'};
 undef $opts->{'source'};
 $opts->{'tap'} = $fcontents;
 $opts->{'tap'} = $fcontents;
@@ -349,6 +349,27 @@ if (!$res) {
     is($tap->{'errors'},0,"No errors encountered uploading case results");
     is($tap->{'errors'},0,"No errors encountered uploading case results");
     is($tap->{'global_status'},5, "Test global result is FAIL on todo pass test w/ bad plan");
     is($tap->{'global_status'},5, "Test global result is FAIL on todo pass test w/ bad plan");
 }
 }
+
+undef $tap;
+#Check bad plan w/ todo pass logic
+$fcontents = "
+todo_pass.test ..
+1..2
+ok 1 - STORAGE TANKS SEARED #TODO todo pass
+# goo
+% mark_status=todo_fail #Appears tanks weren't so sealed after all
+";
+undef $opts->{'source'};
+$opts->{'tap'} = $fcontents;
+$res = exception { $tap = Test::Rail::Parser->new($opts) };
+is($res,undef,"TR Parser doesn't explode on instantiation");
+isa_ok($tap,"Test::Rail::Parser");
+
+if (!$res) {
+    $tap->run();
+    is($tap->{'errors'},0,"No errors encountered uploading case results");
+    is($tap->{'global_status'},7, "Test global result is FAIL on todo pass test w/ bad plan");
+}
 undef $opts->{'tap'};
 undef $opts->{'tap'};
 
 
 #Check autoclose functionality against Run with all tests in run status.
 #Check autoclose functionality against Run with all tests in run status.