瀏覽代碼

More work on #66: move mockModule, proper unit tests for TR::U::Find

George S. Baugh 10 年之前
父節點
當前提交
d2bdc9c7cd

+ 2 - 1
Changes

@@ -11,7 +11,8 @@ Revision history for Perl module TestRail::API
     - Re-factor to use Type::Tiny parameter checking.
     - Re-factor to use Type::Tiny parameter checking.
     - Fix getCaseTypeByName, it's apparently been broken/noncovered this whole time
     - 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 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
+    - Add TestRail::Utils::Find as a backend to testrail-runs & testrail-tests, expand unit tests
+    - Move Test::LWP::UserAgent::TestRailMock to t/lib, no point fretting on it
 
 
 0.028 2015-06-16 TEODESIAN
 0.028 2015-06-16 TEODESIAN
     - Hotfix: forgot to include a module in the prove plugin.  How did this pass compile.t? A mystery.
     - Hotfix: forgot to include a module in the prove plugin.  How did this pass compile.t? A mystery.

+ 0 - 11
bin/testrail-runs

@@ -58,8 +58,6 @@ All options specified thereby are overridden by passing the command-line switche
 
 
 =over 4
 =over 4
 
 
---mock : don't do any real HTTP requests.
-
 --help : show this output
 --help : show this output
 
 
 =back
 =back
@@ -92,7 +90,6 @@ GetOptions(
     'j|project=s'  => \$opts->{'project'},
     'j|project=s'  => \$opts->{'project'},
     'c|config=s@'  => \$opts->{'configs'},
     'c|config=s@'  => \$opts->{'configs'},
     's|status=s@'  => \$opts->{'statuses'},
     's|status=s@'  => \$opts->{'statuses'},
-    'mock'         => \$opts->{'mock'},
     'e|encoding=s' => \$opts->{'encoding'},
     'e|encoding=s' => \$opts->{'encoding'},
     'l|lifo'       => \$opts->{'lifo'},
     'l|lifo'       => \$opts->{'lifo'},
     'm|milesort'   => \$opts->{'milesort'},
     'm|milesort'   => \$opts->{'milesort'},
@@ -103,15 +100,7 @@ if ($opts->{help}) { TestRail::Utils::help(); }
 
 
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project});
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project});
 
 
-if ($opts->{mock}) {
-    use Test::LWP::UserAgent::TestRailMock;
-    $opts->{browser} = $Test::LWP::UserAgent::TestRailMock::mockObject;
-    $opts->{debug} = 1;
-}
-
 my $tr = TestRail::API->new($opts->{apiurl},$opts->{user},$opts->{password},$opts->{'encoding'},$opts->{'debug'});
 my $tr = TestRail::API->new($opts->{apiurl},$opts->{user},$opts->{password},$opts->{'encoding'},$opts->{'debug'});
-$tr->{'browser'} = $opts->{'browser'} if $opts->{'browser'};
-$tr->{'debug'} = 0;
 
 
 my $runs = TestRail::Utils::Find::findRuns($opts,$tr);
 my $runs = TestRail::Utils::Find::findRuns($opts,$tr);
 
 

+ 4 - 40
bin/testrail-tests

@@ -69,8 +69,6 @@ All options specified thereby are overridden by passing the command-line switche
 
 
 =over 4
 =over 4
 
 
---mock : don't do any real HTTP requests. Used only by tests.
-
 --help : show this output
 --help : show this output
 
 
 =back
 =back
@@ -83,6 +81,7 @@ use utf8;
 
 
 use TestRail::API;
 use TestRail::API;
 use TestRail::Utils;
 use TestRail::Utils;
+use TestRail::Utils::Find;
 
 
 use Getopt::Long;
 use Getopt::Long;
 use File::HomeDir qw{my_home};
 use File::HomeDir qw{my_home};
@@ -105,7 +104,6 @@ GetOptions(
     'c|config=s@'     => \$opts->{'configs'},
     'c|config=s@'     => \$opts->{'configs'},
     's|status=s@'     => \$opts->{'statuses'},
     's|status=s@'     => \$opts->{'statuses'},
     'a|assignedto=s@' => \$opts->{'users'},
     'a|assignedto=s@' => \$opts->{'users'},
-    'mock'            => \$opts->{'mock'},
     'm|match=s'       => \$opts->{'match'},
     'm|match=s'       => \$opts->{'match'},
     'no-match=s'      => \$opts->{'no-match'},
     'no-match=s'      => \$opts->{'no-match'},
     'n|no-recurse'    => \$opts->{'no-recurse'},
     'n|no-recurse'    => \$opts->{'no-recurse'},
@@ -117,47 +115,13 @@ if ($opts->{help}) { TestRail::Utils::help(); }
 
 
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project run});
 TestRail::Utils::interrogateUser($opts,qw{apiurl user password project run});
 
 
-if ($opts->{mock}) {
-    use Test::LWP::UserAgent::TestRailMock;
-    $opts->{browser} = $Test::LWP::UserAgent::TestRailMock::mockObject;
-    $opts->{debug} = 1;
-}
-
 my $tr = TestRail::API->new($opts->{apiurl},$opts->{user},$opts->{password},$opts->{'encoding'},$opts->{'debug'});
 my $tr = TestRail::API->new($opts->{apiurl},$opts->{user},$opts->{password},$opts->{'encoding'},$opts->{'debug'});
-$tr->{'browser'} = $opts->{'browser'} if $opts->{'browser'};
-$tr->{'debug'} = 0;
 
 
-my ($project,$plan,$run) = TestRail::Utils::getRunInformation($tr,$opts);
-
-my ($status_ids,$user_ids);
-
-#Process statuses
-if ($opts->{'statuses'}) {
-    eval { @$status_ids = $tr->statusNamesToIds(@{$opts->{'statuses'}}); };
-    if ($@) {
-        print "$@\n";
-        exit 4;
-    }
-}
-
-#Process assignedto ids
-if ($opts->{'users'}) {
-    eval { @$user_ids = $tr->userNamesToIds(@{$opts->{'users'}}); };
-    if ($@) {
-        print "$@\n";
-        exit 5;
-    }
-}
-
-my $cases = $tr->getTests($run->{'id'},$status_ids,$user_ids);
-
-if (!$cases) {
-    print "No cases in TestRail!\n";
-    exit 3;
-}
+my $cases = TestRail::Utils::getTests($opts,$tr);
+die "No cases in TestRail!\n" unless $cases;
 
 
 $opts->{'names-only'} = 1;
 $opts->{'names-only'} = 1;
-my @tests = TestRail::Utils::findTests($opts,@$cases);
+my @tests = TestRail::Utils::Find::findTests($opts,@$cases);
 
 
 print join("\n",@tests)."\n" if scalar(@tests);
 print join("\n",@tests)."\n" if scalar(@tests);
 
 

+ 4 - 0
dist.ini

@@ -116,6 +116,10 @@ stopwords = lockTest
 stopwords = getRunInformation
 stopwords = getRunInformation
 stopwords = assignedto
 stopwords = assignedto
 stopwords = lockname
 stopwords = lockname
+stopwords = lifo
+stopwords = milesort
+stopwords = findRuns
+stopwords = findTests
 
 
 [PkgVersion]
 [PkgVersion]
 [AutoPrereqs]
 [AutoPrereqs]

二進制
dist/TestRail-API-0.029.tar.gz


+ 1 - 64
lib/TestRail/Utils.pm

@@ -10,9 +10,6 @@ use Carp qw{confess cluck};
 use Pod::Perldoc 3.10;
 use Pod::Perldoc 3.10;
 
 
 use Scalar::Util qw{blessed};
 use Scalar::Util qw{blessed};
-use File::Find;
-use Cwd qw{abs_path};
-use File::Basename qw{basename};
 
 
 =head1 SCRIPT HELPER FUNCTIONS
 =head1 SCRIPT HELPER FUNCTIONS
 
 
@@ -91,7 +88,7 @@ sub parseConfig {
     return $results;
     return $results;
 }
 }
 
 
-=head2 getFilenameFromTAPLine($line)
+=head2 getFilenameFromTapLine($line)
 
 
 Analyze TAP output by prove and look for filename boundaries (no other way to figure out what file is run).
 Analyze TAP output by prove and look for filename boundaries (no other way to figure out what file is run).
 Long story short: don't end 'unknown' TAP lines with any number of dots if you don't want it interpreted as a test name.
 Long story short: don't end 'unknown' TAP lines with any number of dots if you don't want it interpreted as a test name.
@@ -171,66 +168,6 @@ sub getRunInformation {
     return ($project, $plan, $run, $milestone);
     return ($project, $plan, $run, $milestone);
 }
 }
 
 
-=head2 findTests(opts,case1,...,caseN)
-
-Given an ARRAY of tests, find tests meeting your criteria (or not) in the specified directory.
-
-=over 4
-
-=item HASHREF C<OPTS> - Options for finding tests:
-
-=over 4
-
-=item STRING C<MATCH> - Only return tests which exist in the path provided.  Mutually exclusive with no-match.
-
-=item STRING C<NO-MATCH> - Only return tests which aren't in the path provided (orphan tests).  Mutually exclusive with match.
-
-=item BOOL C<NO-RECURSE> - Do not do a recursive scan for files.
-
-=item BOOL C<NAMES-ONLY> - Only return the names of the tests rather than the entire test objects.
-
-=back
-
-=item ARRAY C<CASES> - Array of cases to translate to pathnames based on above options.
-
-=back
-
-Returns tests found that meet the criteria laid out in the options.
-Provides absolute path to tests if match is passed; this is the 'full_title' key if names-only is false/undef.
-Dies if mutually exclusive options are passed.
-
-=cut
-
-sub findTests {
-    my ($opts,@cases) = @_;
-
-    confess "Error! match and no-match options are mutually exclusive.\n" if ($opts->{'match'} && $opts->{'no-match'});
-    my @tests = @cases;
-    my (@realtests);
-
-    if ($opts->{'match'} || $opts->{'no-match'}) {
-        my $dir = $opts->{'match'} ? $opts->{'match'} : $opts->{'no-match'};
-        if (!$opts->{'no-recurse'}) {
-            File::Find::find( sub { push(@realtests,$File::Find::name) if -f }, $dir );
-            @tests = grep {my $real = $_->{'title'}; grep { $real eq basename($_) } @realtests} @cases; #XXX if you have dups in your tree, be-ware
-        } else {
-            #Handle special windows case -- glob doesn't prepend abspath
-            @realtests = glob("$dir/*");
-            @tests = map {
-                $_->{'title'} = "$dir/".$_->{'title'} if( $^O eq 'MSWin32' );
-                $_
-            } grep {my $fname = $_->{'title'}; grep { basename($_) eq $fname} @realtests } @cases;
-        }
-        @tests = map {{'title' => $_}} grep {my $otest = basename($_); scalar(grep {basename($_->{'title'}) eq $otest} @tests) == 0} @realtests if $opts->{'no-match'}; #invert the list in this case.
-    }
-
-    @tests = map { abs_path($_->{'title'}) } @tests if $opts->{'match'} && $opts->{'names-only'};
-    @tests = map { $_->{'full_title'} = abs_path($_->{'title'}); $_ } @tests if $opts->{'match'} && !$opts->{'names-only'};
-    @tests = map { $_->{'title'} } @tests if !$opts->{'match'} && $opts->{'names-only'};
-
-    return @tests;
-}
-
 1;
 1;
 
 
 __END__
 __END__

+ 108 - 13
lib/TestRail/Utils/Find.pm

@@ -6,6 +6,14 @@ package TestRail::Utils::Find;
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use Carp qw{confess cluck};
+
+use File::Find;
+use Cwd qw{abs_path};
+use File::Basename qw{basename};
+
+use TestRail::Utils;
+
 =head1 DESCRIPTION
 =head1 DESCRIPTION
 
 
 =head1 FUNCTIONS
 =head1 FUNCTIONS
@@ -31,7 +39,7 @@ Returns ARRAYREF of run definition HASHREFs.
 
 
 sub findRuns {
 sub findRuns {
     my ($opts,$tr) = @_;
     my ($opts,$tr) = @_;
-    my ($status_ids,$user_ids);
+    my ($status_ids);
 
 
     #Process statuses
     #Process statuses
     if ($opts->{'statuses'}) {
     if ($opts->{'statuses'}) {
@@ -41,24 +49,26 @@ sub findRuns {
     my $project = $tr->getProjectByName($opts->{'project'});
     my $project = $tr->getProjectByName($opts->{'project'});
     confess("No such project '$opts->{project}'.\n") if !$project;
     confess("No such project '$opts->{project}'.\n") if !$project;
 
 
-    my @pconfigs = ();
-    @pconfigs = $tr->translateConfigNamesToIds($project->{'id'},$opts->{configs}) if $opts->{'configs'};
+    my $pconfigs = [];
+    $pconfigs = $tr->translateConfigNamesToIds($project->{'id'},$opts->{configs}) if $opts->{'configs'};
 
 
     my ($runs,$plans,$planRuns,$cruns,$found) = ([],[],[],[],0);
     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.
     $runs = $tr->getRuns($project->{'id'}) if (!$opts->{'configs'}); # If configs are passed, global runs are not in consideration.
     $plans = $tr->getPlans($project->{'id'});
     $plans = $tr->getPlans($project->{'id'});
+    @$plans = map {$tr->getPlanByID($_->{'id'})} @$plans;
     foreach my $plan (@$plans) {
     foreach my $plan (@$plans) {
         $cruns = $tr->getChildRuns($plan);
         $cruns = $tr->getChildRuns($plan);
         next if !$cruns;
         next if !$cruns;
         foreach my $run (@$cruns) {
         foreach my $run (@$cruns) {
-            next if scalar(@pconfigs) != scalar(@{$run->{'config_ids'}});
+            next if scalar(@$pconfigs) != scalar(@{$run->{'config_ids'}});
 
 
             #Compare run config IDs against desired, invalidate run if all conditions not satisfied
             #Compare run config IDs against desired, invalidate run if all conditions not satisfied
             $found = 0;
             $found = 0;
             foreach my $cid (@{$run->{'config_ids'}}) {
             foreach my $cid (@{$run->{'config_ids'}}) {
-                $found++ if grep {$_ == $cid} @pconfigs;
+                $found++ if grep {$_ == $cid} @$pconfigs;
             }
             }
-
+            $run->{'created_on'}   = $plan->{'created_on'};
+            $run->{'milestone_id'} = $plan->{'milestone_id'};
             push(@$planRuns, $run) if $found == scalar(@{$run->{'config_ids'}});
             push(@$planRuns, $run) if $found == scalar(@{$run->{'config_ids'}});
         }
         }
     }
     }
@@ -95,25 +105,110 @@ sub findRuns {
     return $runs;
     return $runs;
 }
 }
 
 
-=head2 findTests
+=head2 getTests(opts,testrail)
+
+Get the tests specified by the options passed.
 
 
-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.
+=over 4
 
 
-The primary routine of testrail-tests.
+=item HASHREF C<OPTS> - Options for getting the tests
 
 
 =over 4
 =over 4
 
 
-=item HASHREF C<OPTIONS> - flags acceptable by testrail-tests
+=item STRING C<PROJECT> - name of Project to look for tests in
 
 
-=item TestRail::API C<HANDLE> - TestRail::API object
+=item STRING C<RUN> - name of Run to get tests from
+
+=item STRING C<PLAN> (optional) - name of Plan to get run from
+
+=item ARRAYREF[STRING] C<CONFIGS> (optional) - names of configs run must satisfy, if part of a plan
+
+=item ARRAYREF[STRING] C<USERS> (optional) - names of users to filter cases by assignee
+
+=item ARRAYREF[STRING] C<STATUSES> (optional) - names of statuses to filter cases by
 
 
 =back
 =back
 
 
+=back
+
+Returns ARRAYREF of tests.
+
 =cut
 =cut
 
 
-sub findTests {
+sub getTests {
     my ($opts,$tr) = @_;
     my ($opts,$tr) = @_;
+
+    my ($project,$plan,$run) = TestRail::Utils::getRunInformation($tr,$opts);
+    my ($status_ids,$user_ids);
+
+    #Process statuses
+    @$status_ids = $tr->statusNamesToIds(@{$opts->{'statuses'}}) if $opts->{'statuses'};
+
+    #Process assignedto ids
+    @$user_ids = $tr->userNamesToIds(@{$opts->{'users'}}) if $opts->{'users'};
+
+    my $cases = $tr->getTests($run->{'id'},$status_ids,$user_ids);
+    return $cases;
+}
+
+=head2 findTests(opts,case1,...,caseN)
+
+Given an ARRAY of tests, find tests meeting your criteria (or not) in the specified directory.
+
+=over 4
+
+=item HASHREF C<OPTS> - Options for finding tests:
+
+=over 4
+
+=item STRING C<MATCH> - Only return tests which exist in the path provided.  Mutually exclusive with no-match.
+
+=item STRING C<NO-MATCH> - Only return tests which aren't in the path provided (orphan tests).  Mutually exclusive with match.
+
+=item BOOL C<NO-RECURSE> - Do not do a recursive scan for files.
+
+=item BOOL C<NAMES-ONLY> - Only return the names of the tests rather than the entire test objects.
+
+=back
+
+=item ARRAY C<CASES> - Array of cases to translate to pathnames based on above options.
+
+=back
+
+Returns tests found that meet the criteria laid out in the options.
+Provides absolute path to tests if match is passed; this is the 'full_title' key if names-only is false/undef.
+Dies if mutually exclusive options are passed.
+
+=cut
+
+sub findTests {
+    my ($opts,@cases) = @_;
+
+    confess "Error! match and no-match options are mutually exclusive.\n" if ($opts->{'match'} && $opts->{'no-match'});
+    my @tests = @cases;
+    my (@realtests);
+
+    if ($opts->{'match'} || $opts->{'no-match'}) {
+        my $dir = $opts->{'match'} ? $opts->{'match'} : $opts->{'no-match'};
+        if (!$opts->{'no-recurse'}) {
+            File::Find::find( sub { push(@realtests,$File::Find::name) if -f }, $dir );
+            @tests = grep {my $real = $_->{'title'}; grep { $real eq basename($_) } @realtests} @cases; #XXX if you have dups in your tree, be-ware
+        } else {
+            #Handle special windows case -- glob doesn't prepend abspath
+            @realtests = glob("$dir/*");
+            @tests = map {
+                $_->{'title'} = "$dir/".$_->{'title'} if( $^O eq 'MSWin32' );
+                $_
+            } grep {my $fname = $_->{'title'}; grep { basename($_) eq $fname} @realtests } @cases;
+        }
+        @tests = map {{'title' => $_}} grep {my $otest = basename($_); scalar(grep {basename($_->{'title'}) eq $otest} @tests) == 0} @realtests if $opts->{'no-match'}; #invert the list in this case.
+    }
+
+    @tests = map { abs_path($opts->{'match'}.'/'.$_->{'title'}) } @tests if $opts->{'match'} && $opts->{'names-only'};
+    @tests = map { $_->{'full_title'} = abs_path($opts->{'match'}.'/'.$_->{'title'}); $_ } @tests if $opts->{'match'} && !$opts->{'names-only'};
+    @tests = map { $_->{'title'} } @tests if !$opts->{'match'} && $opts->{'names-only'};
+
+    return @tests;
 }
 }
 
 
 1;
 1;

+ 2 - 1
lib/TestRail/Utils/Lock.pm

@@ -15,6 +15,7 @@ use Type::Params qw( compile );
 
 
 use TestRail::API;
 use TestRail::API;
 use TestRail::Utils;
 use TestRail::Utils;
+use TestRail::Utils::Find;
 
 
 =head1 DESCRIPTION
 =head1 DESCRIPTION
 
 
@@ -85,7 +86,7 @@ sub pickAndLockTest {
     @$cases = sort { $b->{'priority_id'} <=> $a->{'priority_id'} } @$cases; #Sort by priority DESC
     @$cases = sort { $b->{'priority_id'} <=> $a->{'priority_id'} } @$cases; #Sort by priority DESC
 
 
     # Filter by match options
     # Filter by match options
-    @$cases = TestRail::Utils::findTests($opts,@$cases);
+    @$cases = TestRail::Utils::Find::findTests($opts,@$cases);
 
 
     my ($title,$test);
     my ($title,$test);
     while (@$cases) {
     while (@$cases) {

+ 3 - 0
t/App-Prove-Plugin-Testrail.t

@@ -3,6 +3,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 use Test::More 'tests' => 6;
 use Test::More 'tests' => 6;
 use Test::Fatal;
 use Test::Fatal;
 use App::Prove;
 use App::Prove;

+ 3 - 0
t/Test-Rail-Parser.t

@@ -3,6 +3,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 use Scalar::Util qw{reftype};
 use Scalar::Util qw{reftype};
 use TestRail::API;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 use Test::LWP::UserAgent::TestRailMock;

+ 3 - 0
t/TestRail-API-mockOnly.t

@@ -1,6 +1,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 #Test things we can only mock, because the API doesn't support them.
 #Test things we can only mock, because the API doesn't support them.
 
 
 use Test::More 'tests' => 14;
 use Test::More 'tests' => 14;

+ 3 - 0
t/TestRail-API.t

@@ -1,6 +1,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 use TestRail::API;
 use TestRail::API;
 use Test::LWP::UserAgent::TestRailMock;
 use Test::LWP::UserAgent::TestRailMock;
 
 

+ 163 - 0
t/TestRail-Utils-Find.t

@@ -0,0 +1,163 @@
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use Test::More 'tests' => 28;
+use Test::Fatal;
+use Test::Deep;
+use File::Basename qw{dirname};
+
+use TestRail::Utils;
+use TestRail::Utils::Lock;
+use Test::LWP::UserAgent::TestRailMock;
+use File::Basename qw{basename};
+
+#FindRuns tests
+
+my $opts = {
+    'project'    => 'TestProject'
+};
+
+my ($apiurl,$login,$pw) = ('http://testrail.local','bogus','bogus');
+
+my $tr = new TestRail::API($apiurl,$login,$pw,undef,1);
+
+#Mock if necesary
+$tr->{'debug'} = 0;
+
+$tr->{'browser'} = Test::LWP::UserAgent::TestRailMock::lockMockStep0();
+
+my $runs = TestRail::Utils::Find::findRuns($opts,$tr);
+is(ref $runs, 'ARRAY', "FindRuns returns ARRAYREF");
+is(scalar(@$runs),4,"All runs for project found when no other options are passed");
+@$runs = map {$_->{'name'}} @$runs;
+my @expected = qw{OtherOtherSuite TestingSuite FinalRun lockRun};
+cmp_deeply($runs,\@expected,"Tests ordered FIFO by creation date correctly");
+
+$opts->{'lifo'} = 1;
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+@$runs = map {$_->{'name'}} @$runs;
+@expected = qw{lockRun TestingSuite FinalRun OtherOtherSuite};
+cmp_deeply($runs,\@expected,"Tests ordered LIFO by creation date correctly");
+
+$opts->{'milesort'} = 1;
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+@$runs = map {$_->{'name'}} @$runs;
+@expected = qw{OtherOtherSuite TestingSuite FinalRun lockRun};
+cmp_deeply($runs,\@expected,"Tests ordered LIFO by milestone date correctly");
+
+delete $opts->{'lifo'};
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+@$runs = map {$_->{'name'}} @$runs;
+@expected = qw{TestingSuite FinalRun lockRun OtherOtherSuite};
+cmp_deeply($runs,\@expected,"Tests ordered LIFO by milestone date correctly");
+
+delete $opts->{'milesort'};
+
+$opts->{'configs'} = ['eee', 'testConfig'];
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+@$runs = map {$_->{'name'}} @$runs;
+is(scalar(@$runs),0,"Filtering runs by configurations works");
+
+$opts->{'configs'} = ['testConfig'];
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+@$runs = map {$_->{'name'}} @$runs;
+is(scalar(@$runs),3,"Filtering runs by configurations works");
+
+delete $opts->{'configs'};
+$opts->{'statuses'} = ['passed'];
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+is(scalar(@$runs),0,"No passing runs can be found in projects without them");
+
+$opts->{'statuses'} = ['retest'];
+$runs = TestRail::Utils::Find::findRuns($opts,$tr);
+is(scalar(@$runs),1,"Failed runs can be found in projects with them");
+
+#Test testrail-tests
+
+$opts = {
+    'project'    => 'TestProject',
+    'plan'       => 'GosPlan',
+    'run'        => 'Executing the great plan',
+    'match'      => $FindBin::Bin,
+    'configs'    => ['testConfig'],
+    'no-recurse' => 1,
+    'names-only' => 1
+};
+
+my $cases = TestRail::Utils::Find::getTests($opts,$tr);
+my @tests = TestRail::Utils::Find::findTests($opts,@$cases);
+@expected = ("$FindBin::Bin/skipall.test");
+cmp_deeply(\@tests,\@expected,"findTests: match, no-recurse, plan mode, names-only");
+
+delete $opts->{'names-only'};
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+@tests = map {$_->{'full_title'}} @tests;
+cmp_deeply(\@tests,\@expected,"findTests: match, no-recurse, plan mode");
+
+delete $opts->{'match'};
+$opts->{'no-match'} = $FindBin::Bin;
+$opts->{'names-only'} = 1;
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(grep {$_ eq 'skipall.test'} @tests),0,"Tests in tree are not returned in no-match mode");
+is(scalar(grep {$_ eq 'NOT SO SEARED AFTER ALL'} @tests),0,"Tests not in tree that do exist are not returned in no-match mode");
+is(scalar(grep {$_ eq $FindBin::Bin.'/faker.test'} @tests),1,"Orphan Tests in tree ARE returned in no-match mode");
+is(scalar(@tests),26,"Correct number of non-existant cases shown (no-match, names-only)");
+
+$opts->{'configs'} = ['testPlatform1'];
+isnt(exception { TestRail::Utils::Find::getTests($opts,$tr) } , undef,"Correct number of non-existant cases shown (no-match, names-only)");
+$opts->{'configs'} = ['testConfig'];
+
+delete $opts->{'names-only'};
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+my @filtered_tests = grep {defined $_} map {$_->{'full_title'}} @tests;
+is(scalar(@filtered_tests),0,"Full titles not returned in no-match mode");
+is(scalar(@tests),26,"Correct number of nonexistant cases shown in no-match mode");
+
+delete $opts->{'no-recurse'};
+$opts->{'names-only'} = 1;
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),30,"Correct number of non-existant cases shown (no-match, names-only, recurse)");
+
+#mutual excl
+$opts->{'match'} = $FindBin::Bin;
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+isnt(exception {TestRail::Utils::Find::findTests($opts,@$cases)},undef,"match and no-match are mutually exclusive");
+delete $opts->{'no-match'};
+
+delete $opts->{'plan'};
+$opts->{'run'} = 'TestingSuite';
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),1,"Correct number of non-existant cases shown (match, plain run)");
+is(scalar(grep {$_ eq "$FindBin::Bin/skipall.test"} @tests),1,"Tests in tree are returned in match, plain run mode");
+
+#Now that we've made sure configs are ignored...
+$opts->{'plan'} = 'GosPlan';
+$opts->{'run'} = 'Executing the great plan';
+$opts->{'users'} = ['teodesian'];
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),1,"Correct number of cases shown (match, plan run, assignedto pos)");
+is(scalar(grep {$_ eq "$FindBin::Bin/skipall.test"} @tests),1,"Tests in tree are returned filtered by assignee");
+
+$opts->{'users'} = ['billy'];
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),0,"Correct number of cases shown (match, plan run, assignedto neg)");
+
+delete $opts->{'users'};
+$opts->{'statuses'} = ['passed'];
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),1,"Correct number of cases shown (match, plan run, passed)");
+
+$opts->{'statuses'} = ['failed'];
+delete $opts->{'match'};
+$cases = TestRail::Utils::Find::getTests($opts,$tr);
+@tests = TestRail::Utils::Find::findTests($opts,@$cases);
+is(scalar(@tests),0,"Correct number of cases shown (match, plan run, failed)");

+ 3 - 0
t/TestRail-Utils-Lock.t

@@ -1,6 +1,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 use Test::More 'tests' => 11;
 use Test::More 'tests' => 11;
 use Test::Fatal;
 use Test::Fatal;
 use File::Basename qw{dirname};
 use File::Basename qw{dirname};

+ 3 - 0
t/TestRail-Utils.t

@@ -1,6 +1,9 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
 use Test::More 'tests' => 23;
 use Test::More 'tests' => 23;
 use Test::Fatal;
 use Test::Fatal;
 
 

+ 0 - 0
lib/Test/LWP/UserAgent/TestRailMock.pm → t/lib/Test/LWP/UserAgent/TestRailMock.pm


+ 3 - 45
t/testrail-runs.t

@@ -1,52 +1,10 @@
 use strict;
 use strict;
 use warnings;
 use warnings;
 
 
-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/^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});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK looking for runs with passes, which should fail to return results");
-chomp $out;
-is($out,'',"Gets no runs correctly looking for passes");
-
-@args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "CRUSH ALL HUMANS" --mock --status passed});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK looking for runs with passes");
-chomp $out;
-like($out,qr/SEND T-1000 INFILTRATION UNITS BACK IN TIME$/,"Gets run correctly looking for passes");
-
-#TODO check configs for real next time
-@args = ($^X,qw{bin/testrail-runs --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j "TestProject" --mock --config testConfig});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK looking for runs with passes");
-chomp $out;
-is($out,'',"Gets no run correctly when filtering by unassigned config");
+use Test::More 'tests' => 2;
 
 
 #help options
 #help options
-@args = ($^X,qw{bin/testrail-runs --help});
-$out = `@args`;
+my @args = ($^X,qw{bin/testrail-runs --help});
+my $out = `@args`;
 is($? >> 8, 0, "Exit code OK looking for help");
 is($? >> 8, 0, "Exit code OK looking for help");
 like($out,qr/encoding of arguments/i,"Help output OK");
 like($out,qr/encoding of arguments/i,"Help output OK");

+ 0 - 87
t/testrail-tests.t

@@ -3,94 +3,7 @@ use warnings;
 
 
 use Test::More "tests" => 30;
 use Test::More "tests" => 30;
 
 
-#check plan mode
-my @args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" -m t --config testConfig --mock --no-recurse});
-my $out = `@args`;
-is($? >> 8, 0, "Exit code OK running plan mode, no recurse");
-chomp $out;
-like($out,qr/skipall\.test$/,"Gets test correctly in plan mode, no recurse");
-
-#check no-match
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --no-match t --config testConfig --mock});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running plan mode, no match");
-chomp $out;
-unlike($out,qr/skipall\.test/,"Omits test correctly in plan mode, recurse, no-match");
-unlike($out,qr/NOT SO SEARED AFTER ARR/,"Omits non-file test correctly in plan mode, recurse, no-match");
-like($out,qr/faker\.test/,"Omits non-file test correctly in plan mode, recurse, no-match");
-
-#check no-match, no recurse
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --no-match t --config testConfig --mock --no-recurse});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running plan mode, no match, no recurse");
-chomp $out;
-unlike($out,qr/skipall\.test/,"Omits test correctly in plan mode, no recurse, no-match");
-unlike($out,qr/NOT SO SEARED AFTER ARR/,"Omits non-file test correctly in plan mode, no recurse, no-match");
-like($out,qr/faker\.test/,"Omits non-file test correctly in plan mode, no recurse, no-match");
-
-
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --config testConfig -m t --mock});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running plan mode, recurse");
-chomp $out;
-like($out,qr/skipall\.test$/,"Gets test correctly in plan mode, recurse");
-
-#check non plan mode
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -r "TestingSuite" -m t --mock --no-recurse});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running no plan mode, no recurse");
-chomp $out;
-like($out,qr/skipall\.test$/,"Gets test correctly in no plan mode, no recurse");
-
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -r "TestingSuite" -m t --mock});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running no plan mode, recurse");
-chomp $out;
-like($out,qr/skipall\.test$/,"Gets test correctly in no plan mode, recurse");
-
-#Negative case, filtering by config
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" -m t --mock --config testPlatform1});
-$out = `@args`;
-isnt($? >> 8, 0, "Exit code not OK when passing invalid configs for plan");
-
-#check assignedto filters
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --mock --config "testConfig" --assignedto teodesian});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK when filtering by assignment");
-like($out,qr/skipall\.test$/,"Gets test correctly when filtering by assignment");
-
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --mock --config "testConfig" --assignedto billy});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK when filtering by assignment");
-chomp $out;
-is($out,"","Gets no tests correctly when filtering by wrong assignment");
-
-#check status filters
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" -m t --mock --config "testConfig" --status "passed"});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK when filtering by status");
-like($out,qr/skipall\.test$/,"Gets test correctly when filtering by status");
-
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -p "GosPlan" -r "Executing the great plan" --mock --config "testConfig" --status "failed"});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK when filtering by status");
-chomp $out;
-is($out,"","Gets no tests correctly when filtering by wrong status");
-
-#Verify no-match returns non path
-@args = ($^X,qw{bin/testrail-tests --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -r "TestingSuite" --mock});
-$out = `@args`;
-is($? >> 8, 0, "Exit code OK running no plan mode, no recurse");
-chomp $out;
-like($out,qr/\nskipall\.test$/,"Gets test correctly in no plan mode, no recurse");
-
-#Verify no-match returns non path
 @args = ($^X,qw{bin/testrail-tests --help});
 @args = ($^X,qw{bin/testrail-tests --help});
 $out = `@args`;
 $out = `@args`;
 is($? >> 8, 0, "Exit code OK asking for help");
 is($? >> 8, 0, "Exit code OK asking for help");
 like($out,qr/encoding of arguments/i,"Help output OK");
 like($out,qr/encoding of arguments/i,"Help output OK");
-
-#Verify no-match and match are mutually exclusive
-@args = ($^X,qw{bin/testrail-tests --no-match t/ --match t/qa --apiurl http://testrail.local --user "test@fake.fake" --password "fake" -j TestProject -r "TestingSuite" --mock});
-$out = `@args`;
-isnt($? >> 8, 0, "Exit code not OK asking for mutually exclusive match options");

+ 1 - 1
tidyall.ini

@@ -1,3 +1,3 @@
 [PerlTidy]
 [PerlTidy]
-select = **/*.{pl,pm,t}
+select = {lib,bin}/**/*
 argv = -noll -it=2
 argv = -noll -it=2