Forráskód Böngészése

Fix #26: getRuns/getPlans now get all runs/plans

George S. Baugh 10 éve
szülő
commit
4324428141
4 módosított fájl, 178 hozzáadás és 63 törlés
  1. 51 54
      lib/Test/LWP/UserAgent/TestRailMock.pm
  2. 98 6
      lib/TestRail/API.pm
  3. 23 1
      t/TestRail-API.t
  4. 6 2
      t/arg_types.t

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 51 - 54
lib/Test/LWP/UserAgent/TestRailMock.pm


+ 98 - 6
lib/TestRail/API.pm

@@ -86,6 +86,7 @@ sub new {
         configurations   => {},
         tr_fields        => undef,
         default_request  => undef,
+        global_limit     => 250, #Discovered by experimentation
         browser          => new LWP::UserAgent()
     };
 
@@ -156,6 +157,9 @@ sub _doRequest {
 
     my $response = $self->{'browser'}->request($req);
 
+    #use Data::Dumper;
+    #print Dumper($path,'200','OK',$response->headers,$response->content);
+
     return $response if !defined($response); #worst case
     if ($response->code == 403) {
         cluck "ERROR: Access Denied.";
@@ -1035,6 +1039,8 @@ sub deleteRun {
 =head2 B<getRuns (project_id)>
 
 Get all runs for specified project.
+To do this, it must make (no. of runs/250) HTTP requests.
+This is due to the maximum resultset limit enforced by testrail.
 
 =over 4
 
@@ -1052,9 +1058,51 @@ sub getRuns {
     my ($self,$project_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
     confess("Project ID must be integer") unless $self->_checkInteger($project_id);
-    return $self->_doRequest("index.php?/api/v2/get_runs/$project_id");
+    my $initial_runs = $self->getRunsPaginated($project_id,$self->{'global_limit'},0);
+    return $initial_runs unless (reftype($initial_runs) || 'undef') eq 'ARRAY';
+    my $runs = [];
+    push(@$runs,@$initial_runs);
+    my $offset = 1;
+    while (scalar(@$initial_runs) == $self->{'global_limit'}) {
+        $initial_runs = $self->getRunsPaginated($project_id,$self->{'global_limit'},($self->{'global_limit'} * $offset));
+        push(@$runs,@$initial_runs);
+        $offset++;
+    }
+    return $runs;
 }
 
+=head2 B<getRunsPaginated (project_id,limit,offset)>
+
+Get some runs for specified project.
+
+=over 4
+
+=item INTEGER C<PROJECT_ID> - ID of parent project
+
+=item INTEGER C<LIMIT> - Number of runs to return.
+
+=item INTEGER C<OFFSET> - Page of runs to return.
+
+=back
+
+Returns ARRAYREF of run definition HASHREFs.
+
+    $someRuns = $tr->getRunsPaginated(6969,22,4);
+
+=cut
+
+sub getRunsPaginated {
+    my ($self,$project_id,$limit,$offset) = @_;
+    confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Limit must be integer") unless !defined($limit) || $self->_checkInteger($limit);
+    confess("Offset must be integer") unless !defined($offset) || $self->_checkInteger($offset);
+    confess("Limit greater than ".$self->{'global_limit'}) if $limit > $self->{'global_limit'};
+    my $apiurl = "index.php?/api/v2/get_runs/$project_id";
+    $apiurl .= "&offset=$offset" if $offset;
+    $apiurl .= "&limit=$limit" if $limit;
+    return $self->_doRequest($apiurl);
+}
 
 =head2 B<getRunByName (project_id,name)>
 
@@ -1255,9 +1303,10 @@ sub deletePlan {
     return $result;
 }
 
-=head2 B<getPlans (project_id,get_runs)>
+=head2 B<getPlans (project_id)>
 
-Gets specified test plans.
+Gets all test plans in specified project.
+Like getRuns, must make multiple HTTP requests when the number of results exceeds 250.
 
 =over 4
 
@@ -1265,12 +1314,12 @@ Gets specified test plans.
 
 =back
 
-Returns ARRAYREF of plan definition HASHREFs.
+Returns ARRAYREF of all plan definition HASHREFs in a project.
 
     $tr->getPlans(8);
 
 Does not contain any information about child test runs.
-Use getRunByID or getRunByName if you want that, in particular if you are interested in using getChildRunByName.
+Use getPlanByID or getPlanByName if you want that, in particular if you are interested in using getChildRunByName.
 
 =cut
 
@@ -1278,7 +1327,50 @@ sub getPlans {
     my ($self,$project_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
     confess("Project ID must be integer") unless $self->_checkInteger($project_id);
-    return $self->_doRequest("index.php?/api/v2/get_plans/$project_id");
+    my $initial_plans = $self->getPlansPaginated($project_id,$self->{'global_limit'},0);
+    return $initial_plans unless (reftype($initial_plans) || 'undef') eq 'ARRAY';
+    my $plans = [];
+    push(@$plans,@$initial_plans);
+    my $offset = 1;
+    while (scalar(@$initial_plans) == $self->{'global_limit'}) {
+        $initial_plans = $self->getPlansPaginated($project_id,$self->{'global_limit'},($self->{'global_limit'} * $offset));
+        push(@$plans,@$initial_plans);
+        $offset++;
+    }
+    return $plans;
+}
+
+=head2 B<getPlansPaginated (project_id,limit,offset)>
+
+Get some plans for specified project.
+
+=over 4
+
+=item INTEGER C<PROJECT_ID> - ID of parent project
+
+=item INTEGER C<LIMIT> - Number of plans to return.
+
+=item INTEGER C<OFFSET> - Page of plans to return.
+
+=back
+
+Returns ARRAYREF of plan definition HASHREFs.
+
+    $someRuns = $tr->getPlansPaginated(6969,222,44);
+
+=cut
+
+sub getPlansPaginated {
+    my ($self,$project_id,$limit,$offset) = @_;
+    confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Limit must be integer") unless !defined($limit) || $self->_checkInteger($limit);
+    confess("Offset must be integer") unless !defined($offset) || $self->_checkInteger($offset);
+    confess("Limit greater than ".$self->{'global_limit'}) if $limit > $self->{'global_limit'};
+    my $apiurl = "index.php?/api/v2/get_plans/$project_id";
+    $apiurl .= "&offset=$offset" if $offset;
+    $apiurl .= "&limit=$limit" if $limit;
+    return $self->_doRequest($apiurl);
 }
 
 =head2 B<getPlanByName (project_id,name)>

+ 23 - 1
t/TestRail-API.t

@@ -4,7 +4,7 @@ use warnings;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 
-use Test::More tests => 57;
+use Test::More tests => 59;
 use Test::Fatal;
 use Scalar::Util 'reftype';
 use ExtUtils::MakeMaker qw{prompt};
@@ -151,6 +151,28 @@ my $t_config_ids = $tr->translateConfigNamesToIds($new_project->{'id'},\@config_
 @$t_config_ids = sort(@$t_config_ids);
 is_deeply(\@config_ids,$t_config_ids, "Can correctly translate Project names to IDs");
 
+############################################################
+# TestRail arbitrarily limits many calls to 250 result sets.
+# Let's make sure our getters actually get everything.
+############################################################
+
+#Check get_plans
+foreach my $i (0..$tr->{'global_limit'}) {
+    $tr->createPlan($new_project->{'id'},$plan_name,"PETE & RE-PIOTR");
+}
+is(scalar(@{$tr->getPlans($new_project->{'id'})}),($tr->{'global_limit'} + 2),"Can get list of plans beyond ".$tr->{'global_limit'});
+
+
+#Check get_runs
+foreach my $i (0..$tr->{'global_limit'}) {
+    $tr->createRun($new_project->{'id'},$new_suite->{'id'},$run_name,"ACQUIRE CLOTHES, BOOTS AND MOTORCYCLE");
+}
+is(scalar(@{$tr->getRuns($new_project->{'id'})}),($tr->{'global_limit'} + 2),"Can get list of runs beyond ".$tr->{'global_limit'});
+
+##########
+# Clean up
+##########
+
 #Delete a plan
 ok($tr->deletePlan($new_plan->{'id'}),"Can delete plan");
 

+ 6 - 2
t/arg_types.t

@@ -2,7 +2,7 @@ use strict;
 use warnings;
 
 use TestRail::API;
-use Test::More 'tests' => 129;
+use Test::More 'tests' => 133;
 use Test::Fatal;
 use Class::Inspector;
 use Test::LWP::UserAgent;
@@ -60,7 +60,9 @@ isnt( exception {$tr->getTests() },undef,'getTests returns error when no argumen
 isnt( exception {$tr->getTestSuites() },undef,'getTestSuites returns error when no arguments are passed');
 isnt( exception {$tr->getSections() },undef,'getSections returns error when no arguments are passed');
 isnt( exception {$tr->getRuns() },undef,'getRuns returns error when no arguments are passed');
+isnt( exception {$tr->getRunsPaginated() },undef,'getRunsPaginated returns error when no arguments are passed');
 isnt( exception {$tr->getPlans() },undef,'getPlans returns error when no arguments are passed');
+isnt( exception {$tr->getPlansPaginated() },undef,'getPlansPaginated returns error when no arguments are passed');
 isnt( exception {$tr->getMilestones() },undef,'getMilestones returns error when no arguments are passed');
 isnt( exception {$tr->getConfigurationGroups() },undef,'getConfigurations returns error when no arguments are passed');
 isnt( exception {$tr->getConfigurations() },undef,'getConfigurationGroups returns error when no arguments are passed');
@@ -75,14 +77,16 @@ is(exception {$tr->deleteMilestone(1)},       undef,'deleteMilestone returns no
 is(exception {$tr->deletePlan(1)},            undef,'deletePlan returns no error when int arg passed');
 is(exception {$tr->deleteProject(1)},         undef,'deleteProject returns no error when int arg passed');
 is(exception {$tr->deleteRun(1)},             undef,'deleteRun returns no error when int arg passed');
-is(exception {$tr->deleteSection(1)},        undef,'deleteSection returns no error when int arg passed');
+is(exception {$tr->deleteSection(1)},         undef,'deleteSection returns no error when int arg passed');
 is(exception {$tr->deleteTestSuite(1)},       undef,'deleteTestSuite returns no error when int arg passed');
 is(exception {$tr->getCaseByID(1)},           undef,'getCaseByID returns no error when int arg passed');
 is(exception {$tr->getRuns(1)},               undef,'getRuns returns no error when int arg passed');
+is(exception {$tr->getRunsPaginated(1)},      undef,'getRunsPaginated returns no error when int arg passed');
 is(exception {$tr->getSectionByID(1)},        undef,'getSectionByID returns no error when int arg passed');
 is(exception {$tr->getTestByID(1)},           undef,'getTestByID returns no error when int arg passed');
 is(exception {$tr->getTestSuiteByID(1)},      undef,'getTestSuiteByID returns no error when int arg passed');
 is(exception {$tr->getPlans(1)},              undef,'getPlans returns no error when int arg passed');
+is(exception {$tr->getPlansPaginated(1)},     undef,'getPlansPaginated returns no error when int arg passed');
 is(exception {$tr->getProjectByID(1)},        undef,'getProjectByID returns no error when int arg passed');
 is(exception {$tr->getRunByID(1)},            undef,'getRunByID returns no error when int arg passed');
 is(exception {$tr->getTestSuites(1)},         undef,'getTestSuites returns no error when int arg passed');

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott