Prechádzať zdrojové kódy

More progress on #66; need to work on unit tests still though.

George S. Baugh 10 rokov pred
rodič
commit
2981e6c3db

+ 2 - 0
Changes

@@ -10,6 +10,8 @@ Revision history for Perl module TestRail::API
     - Fix an issue where statusNamesToIDs would return status IDs in the wrong order.
     - Re-factor to use Type::Tiny parameter checking.
     - Fix getCaseTypeByName, it's apparently been broken/noncovered this whole time
+    - Add options to sort FIFO/LIFO by creation, milestone due date in testrail-runs
+    - Add TestRail::Utils::Find as a backend to testrail-runs, expand unit tests
 
 0.028 2015-06-16 TEODESIAN
     - Hotfix: forgot to include a module in the prove plugin.  How did this pass compile.t? A mystery.

+ 11 - 57
bin/testrail-runs

@@ -39,6 +39,13 @@ All mandatory options not passed with the above switches, or in your ~/.testrail
 
 -e --encoding : Character encoding of arguments.  Defaults to UTF-8. See L<Encode::Supported> for supported encodings.
 
+-l --lifo     : LIFO sorting of results.  Defaults to FIFO sort if not passed.
+
+-m --milesort : Sort by milestone due time.  Defaults to sorting by run creation time if not passed.
+
+Be aware that when sorting by milestone, if a run has no milestone set, it is considered "earlier" than anything else by perl's comparison routines.
+Ergo if they are the lowest priority, you should consider running LIFO.
+
 =back
 
 =head1 CONFIGURATION FILE
@@ -65,6 +72,7 @@ use utf8;
 
 use TestRail::API;
 use TestRail::Utils;
+use TestRail::Utils::Find;
 
 use Getopt::Long;
 use File::HomeDir qw{my_home};
@@ -86,6 +94,8 @@ GetOptions(
     's|status=s@'  => \$opts->{'statuses'},
     'mock'         => \$opts->{'mock'},
     'e|encoding=s' => \$opts->{'encoding'},
+    'l|lifo'       => \$opts->{'lifo'},
+    'm|milesort'   => \$opts->{'milesort'},
     'h|help'       => \$opts->{'help'}
 );
 
@@ -103,63 +113,7 @@ my $tr = TestRail::API->new($opts->{apiurl},$opts->{user},$opts->{password},$opt
 $tr->{'browser'} = $opts->{'browser'} if $opts->{'browser'};
 $tr->{'debug'} = 0;
 
-my ($status_ids,$user_ids);
-
-#Process statuses
-if ($opts->{'statuses'}) {
-    eval { @$status_ids = $tr->statusNamesToIds(@{$opts->{'statuses'}}); };
-    if ($@) {
-        print "$@\n";
-        exit 4;
-    }
-}
-
-my $project = $tr->getProjectByName($opts->{'project'});
-if (!$project) {
-    print "No such project '$opts->{project}'.\n";
-    exit 6;
-}
-
-my @pconfigs;
-if (defined $opts->{configs}) {
-    my $avail_configs = $tr->getConfigurations($project->{'id'});
-    my ($cname);
-    @pconfigs = map {$_->{'id'}} grep { $cname = $_->{'name'}; grep {$_ eq $cname} @{$opts->{configs}} } @$avail_configs; #Get a list of IDs from the names passed
-}
-
-if (defined($opts->{configs}) && (scalar(@pconfigs) != scalar(@{$opts->{configs}}))) {
-    print("One or more configurations passed does not exist in your project!\n");
-    exit 7;
-}
-
-my ($runs,$plans,$planRuns,$cruns,$found) = ([],[],[],[],0);
-$runs = $tr->getRuns($project->{'id'}) if (!$opts->{'configs'}); # If configs are passed, global runs are not in consideration.
-$plans = $tr->getPlans($project->{'id'});
-foreach my $plan (@$plans) {
-    $cruns = $tr->getChildRuns($plan);
-    next if !$cruns;
-    foreach my $run (@$cruns) {
-        next if scalar(@pconfigs) != scalar(@{$run->{'config_ids'}});
-
-        #Compare run config IDs against desired, invalidate run if all conditions not satisfied
-        $found = 0;
-        foreach my $cid (@{$run->{'config_ids'}}) {
-            $found++ if grep {$_ == $cid} @pconfigs;
-        }
-
-        push(@$planRuns, $run) if $found == scalar(@{$run->{'config_ids'}});
-    }
-}
-
-push(@$runs,@$planRuns);
-
-if ($opts->{'statuses'}) {
-    @$runs =  $tr->getRunSummary(@$runs);
-    @$runs = grep { defined($_->{'run_status'}) } @$runs; #Filter stuff with no results
-    foreach my $status (@{$opts->{'statuses'}}) {
-        @$runs = grep { $_->{'run_status'}->{$status} } @$runs; #If it's positive, keep it.  Otherwise forget it.
-    }
-}
+my $runs = TestRail::Utils::Find::findRuns($opts,$tr);
 
 @$runs = map {$_->{name}} @$runs;
 print join("\n",@$runs)."\n" if scalar(@$runs);

+ 1 - 1
lib/Test/LWP/UserAgent/TestRailMock.pm

@@ -606,7 +606,7 @@ $VAR4 = bless( {
                }, 'HTTP::Headers' );
 $VAR5 = '[
     {"id":1,"suite_id":9,"name":"TestingSuite","description":"ACQUIRE CLOTHES, BOOTS AND MOTORCYCLE","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":1,"retest_count":0,"failed_count":0,"custom_status1_count":0,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":0,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":9,"plan_id":null,"created_on":1419364929,"created_by":1,"url":"http:\\/\\/testrail.local\\/\\/index.php?\\/runs\\/view\\/22"},
-    {"id":2,"suite_id":9,"name":"OtherOtherSuite","description":"bah","completed_on":null,"milestone_id":8},
+    {"id":2,"suite_id":9,"name":"OtherOtherSuite","description":"bah","completed_on":null,"milestone_id":8, "created_on":1},
     {"id":3,"suite_id":9,"name":"FinalRun","description":"Tests finality","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":0,"retest_count":0,"failed_count":0,"custom_status1_count":1,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":0,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":9,"plan_id":null,"created_on":1419364929,"created_by":1,"url":"http:\\/\\/testrail.local\\/\\/index.php?\\/runs\\/view\\/22"},{"id":1099,"suite_id":5,"name":"lockRun","description":"Locky tests","milestone_id":null,"assignedto_id":null,"include_all":true,"is_completed":false,"completed_on":null,"config":null,"config_ids":[],"passed_count":0,"blocked_count":0,"untested_count":0,"retest_count":5,"failed_count":0,"custom_status1_count":0,"custom_status2_count":0,"custom_status3_count":0,"custom_status4_count":1,"custom_status5_count":0,"custom_status6_count":0,"custom_status7_count":0,"project_id":2,"plan_id":null,"created_on":1437073290,"created_by":1,"url":"http:\\/\\/testrail.local\\/index.php?\\/runs\\/view\\/1099"}
 ]';
 $mockObject->map_response(qr/\Q$VAR1\E/,HTTP::Response->new($VAR2, $VAR3, $VAR4, $VAR5));

+ 125 - 0
lib/TestRail/Utils/Find.pm

@@ -0,0 +1,125 @@
+# PODNAME: TestRail::Utils::Find
+# ABSTRACT: Find runs and tests according to user specifications.
+
+package TestRail::Utils::Find;
+
+use strict;
+use warnings;
+
+=head1 DESCRIPTION
+
+=head1 FUNCTIONS
+
+=head2 findRuns
+
+Find runs based on the options HASHREF provided.
+See the documentation for L<testrail-runs>, as the long argument names there correspond to hash keys.
+
+The primary routine of testrail-runs.
+
+=over 4
+
+=item HASHREF C<OPTIONS> - flags acceptable by testrail-tests
+
+=item TestRail::API C<HANDLE> - TestRail::API object
+
+=back
+
+Returns ARRAYREF of run definition HASHREFs.
+
+=cut
+
+sub findRuns {
+    my ($opts,$tr) = @_;
+    my ($status_ids,$user_ids);
+
+    #Process statuses
+    if ($opts->{'statuses'}) {
+        @$status_ids = $tr->statusNamesToIds(@{$opts->{'statuses'}});
+    }
+
+    my $project = $tr->getProjectByName($opts->{'project'});
+    confess("No such project '$opts->{project}'.\n") if !$project;
+
+    my @pconfigs = ();
+    @pconfigs = $tr->translateConfigNamesToIds($project->{'id'},$opts->{configs}) if $opts->{'configs'};
+
+    my ($runs,$plans,$planRuns,$cruns,$found) = ([],[],[],[],0);
+    $runs = $tr->getRuns($project->{'id'}) if (!$opts->{'configs'}); # If configs are passed, global runs are not in consideration.
+    $plans = $tr->getPlans($project->{'id'});
+    foreach my $plan (@$plans) {
+        $cruns = $tr->getChildRuns($plan);
+        next if !$cruns;
+        foreach my $run (@$cruns) {
+            next if scalar(@pconfigs) != scalar(@{$run->{'config_ids'}});
+
+            #Compare run config IDs against desired, invalidate run if all conditions not satisfied
+            $found = 0;
+            foreach my $cid (@{$run->{'config_ids'}}) {
+                $found++ if grep {$_ == $cid} @pconfigs;
+            }
+
+            push(@$planRuns, $run) if $found == scalar(@{$run->{'config_ids'}});
+        }
+    }
+
+    push(@$runs,@$planRuns);
+
+    if ($opts->{'statuses'}) {
+        @$runs =  $tr->getRunSummary(@$runs);
+        @$runs = grep { defined($_->{'run_status'}) } @$runs; #Filter stuff with no results
+        foreach my $status (@{$opts->{'statuses'}}) {
+            @$runs = grep { $_->{'run_status'}->{$status} } @$runs; #If it's positive, keep it.  Otherwise forget it.
+        }
+    }
+
+    #Sort FIFO/LIFO by milestone or creation date of run
+    my $sortkey = 'created_on';
+    if ($opts->{'milesort'}) {
+        @$runs = map {
+            my $run = $_;
+            $run->{'milestone'} = $tr->getMilestoneByID($run->{'milestone_id'}) if $run->{'milestone_id'};
+            my $milestone = $run->{'milestone'} ? $run->{'milestone'}->{'due_on'} : 0;
+            $run->{'due_on'} = $milestone;
+            $run
+        } @$runs;
+        $sortkey = 'due_on';
+    }
+
+    if ($opts->{'lifo'}) {
+        @$runs = sort { $b->{$sortkey} <=> $a->{$sortkey} } @$runs;
+    } else {
+        @$runs = sort { $a->{$sortkey} <=> $b->{$sortkey} } @$runs;
+    }
+
+    return $runs;
+}
+
+=head2 findTests
+
+Find tests based on the options HASHREF provided.
+See the documentation for L<testrail-tests>, as the long argument names there correspond to hash keys.
+
+The primary routine of testrail-tests.
+
+=over 4
+
+=item HASHREF C<OPTIONS> - flags acceptable by testrail-tests
+
+=item TestRail::API C<HANDLE> - TestRail::API object
+
+=back
+
+=cut
+
+sub findTests {
+    my ($opts,$tr) = @_;
+}
+
+1;
+
+__END__
+
+=head1 SPECIAL THANKS
+
+Thanks to cPanel Inc, for graciously funding the creation of this module.

+ 17 - 2
t/testrail-runs.t

@@ -1,14 +1,29 @@
 use strict;
 use warnings;
 
-use Test::More 'tests' => 10;
+use Test::More 'tests' => 14;
 
 #check status filters
 my @args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "TestProject" --mock});
 my $out = `@args`;
 is($? >> 8, 0, "Exit code OK looking for runs with passes");
 chomp $out;
-like($out,qr/^TestingSuite\nOtherOtherSuite\nFinalRun\nlockRun$/,"Gets run correctly looking for passes");
+like($out,qr/^OtherOtherSuite\nTestingSuite\nFinalRun\nlockRun$/,"Gets run correctly looking for passes");
+
+#check LIFO sort
+@args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "TestProject" --lifo --mock});
+$out = `@args`;
+is($? >> 8, 0, "Exit code OK looking for runs with passes");
+chomp $out;
+like($out,qr/^lockRun\nTestingSuite\nFinalRun\nOtherOtherSuite$/,"LIFO sort works");
+
+#check milesort
+@args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "TestProject" --milesort --mock});
+$out = `@args`;
+is($? >> 8, 0, "Exit code OK looking for runs with passes");
+chomp $out;
+like($out,qr/^TestingSuite\nFinalRun\nlockRun\nOtherOtherSuite$/,"milesort works");
+
 
 #check status filters
 @args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "TestProject" --mock --status passed});