Ver código fonte

Add type checking and so forth, use LWP::UA mock to speed things up

George S. Baugh 11 anos atrás
pai
commit
5be5fd82b4
5 arquivos alterados com 245 adições e 53 exclusões
  1. 2 0
      Changes
  2. 133 10
      lib/TestRail/API.pm
  3. 64 0
      t/arg_types.t
  4. 1 1
      t/author-classSafety.t
  5. 45 42
      t/server_dead.t

+ 2 - 0
Changes

@@ -2,9 +2,11 @@ Revision history for Perl module TestRail::API
 
 0.012 2014-12-?? TEODESIAN
     - DZIL tidying
+    - Re-enabled some of the critic tests, fixed a few related issues
     - Improve safety of constructor, try to die with helpful messages as soon as possible
     - Add class usage checks and test for that as author tests
     - Add tests for the server going away, and fix issues encountered therein.
+    - Add fatal type checking of inputs for all methods, add test to make sure exceptions thrown correctly
 
 0.011 2014-12-04 TEODESIAN
     - Converted to using dzil, and testing using TestingMania

+ 133 - 10
lib/TestRail/API.pm

@@ -216,6 +216,7 @@ Returns user def HASHREF.
 sub getUserByID {
     my ($self,$user) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("User ID must be integer") unless $self->_checkInteger($user);
     $self->getUsers() if !defined($self->{'user_cache'});
     return -500 if (!defined($self->{'user_cache'}) || (reftype($self->{'user_cache'}) || 'undef') ne 'ARRAY');
     foreach my $usr (@{$self->{'user_cache'}}) {
@@ -227,6 +228,7 @@ sub getUserByID {
 sub getUserByName {
     my ($self,$user) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("User must be string") unless $self->_checkString($user);
     $self->getUsers() if !defined($self->{'user_cache'});
     return -500 if (!defined($self->{'user_cache'}) || (reftype($self->{'user_cache'}) || 'undef') ne 'ARRAY');
     foreach my $usr (@{$self->{'user_cache'}}) {
@@ -236,12 +238,13 @@ sub getUserByName {
 }
 
 sub getUserByEmail {
-    my ($self,$user) = @_;
+    my ($self,$email) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Email must be string") unless $self->_checkString($email);
     $self->getUsers() if !defined($self->{'user_cache'});
     return -500 if (!defined($self->{'user_cache'}) || (reftype($self->{'user_cache'}) || 'undef') ne 'ARRAY');
     foreach my $usr (@{$self->{'user_cache'}}) {
-        return $usr if $usr->{'email'} eq $user;
+        return $usr if $usr->{'email'} eq $email;
     }
     return 0;
 }
@@ -273,8 +276,11 @@ Returns project definition HASHREF on success, false otherwise.
 sub createProject {
     my ($self,$name,$desc,$announce) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project name must be string") unless $self->_checkString($name);
     $desc     //= 'res ipsa loquiter';
     $announce //= 0;
+    confess("Project description must be string") unless $self->_checkString($desc);
+    confess("Announce must be integer") unless $self->_checkInteger($announce);
 
     my $input = {
         name              => $name,
@@ -307,6 +313,7 @@ Returns BOOLEAN.
 sub deleteProject {
     my ($self,$proj) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($proj);
     my $result = $self->_doRequest('index.php?/api/v2/delete_project/'.$proj,'POST');
     return $result;
 }
@@ -359,7 +366,7 @@ Returns desired project def HASHREF, false otherwise.
 sub getProjectByName {
     my ($self,$project) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
-    confess "No project provided." unless $project;
+    confess("Project must be string.") unless $self->_checkString($project);
 
     #See if we already have the project list...
     my $projects = $self->{'testtree'};
@@ -394,7 +401,8 @@ Returns desired project def HASHREF, false otherwise.
 sub getProjectByID {
     my ($self,$project) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
-    confess "No project provided." unless $project;
+    confess("No project provided.") unless $project;
+    confess("Project ID must be integer") unless $self->_checkInteger($project);
 
     #See if we already have the project list...
     my $projects = $self->{'testtree'};
@@ -433,7 +441,10 @@ Returns TS definition HASHREF on success, false otherwise.
 sub createTestSuite {
     my ($self,$project_id,$name,$details) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Name must be a string") unless $self->_checkString($name);
     $details ||= 'res ipsa loquiter';
+    confess("Project details must be a string") unless $self->_checkString($details);
 
     my $input = {
         name        => $name,
@@ -464,6 +475,7 @@ Returns BOOLEAN.
 sub deleteTestSuite {
     my ($self,$suite_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
 
     my $result = $self->_doRequest('index.php?/api/v2/delete_suite/'.$suite_id,'POST');
     return $result;
@@ -489,6 +501,7 @@ Returns ARRAYREF of testsuite definition HASHREFs, 0 on error.
 sub getTestSuites {
     my ($self,$proj) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($proj);
     return $self->_doRequest('index.php?/api/v2/get_suites/'.$proj);
 }
 
@@ -513,6 +526,8 @@ Returns desired testsuite definition HASHREF, false otherwise.
 sub getTestSuiteByName {
     my ($self,$project_id,$testsuite_name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Testsuite Name must be String") unless $self->_checkString($testsuite_name);
 
     #TODO cache
     my $suites = $self->getTestSuites($project_id);
@@ -542,6 +557,7 @@ Returns desired testsuite definition HASHREF, false otherwise.
 sub getTestSuiteByID {
     my ($self,$testsuite_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Testsuite ID must be integer") unless $self->_checkInteger($testsuite_id);
 
     my $result = $self->_doRequest('index.php?/api/v2/get_suite/'.$testsuite_id);
     return $result;
@@ -574,6 +590,10 @@ Returns new section definition HASHREF, false otherwise.
 sub createSection {
     my ($self,$project_id,$suite_id,$name,$parent_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
+    confess("Section name must be string") unless $self->_checkString($name);
+    confess("Parent section ID must be integer") unless !defined($parent_id) || $self->_checkInteger($parent_id);
 
     my $input = {
         name     => $name,
@@ -605,6 +625,7 @@ Returns BOOLEAN.
 sub deleteSection {
     my ($self,$section_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Section ID must be integer") unless $self->_checkInteger($section_id);
 
     my $result = $self->_doRequest('index.php?/api/v2/delete_section/'.$section_id,'POST');
     return $result;
@@ -632,6 +653,8 @@ Returns ARRAYREF of section definition HASHREFs.
 sub getSections {
     my ($self,$project_id,$suite_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
     return $self->_doRequest("index.php?/api/v2/get_sections/$project_id&suite_id=$suite_id");
 }
 
@@ -656,6 +679,7 @@ Returns section definition HASHREF.
 sub getSectionByID {
     my ($self,$section_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Section ID must be integer") unless $self->_checkInteger($section_id);
     return $self->_doRequest("index.php?/api/v2/get_section/$section_id");
 }
 
@@ -682,6 +706,9 @@ Returns section definition HASHREF.
 sub getSectionByName {
     my ($self,$project_id,$suite_id,$section_name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be an integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be an integer") unless $self->_checkInteger($suite_id);
+    confess("Section Name must be a string") unless $self->_checkString($section_name);
     my $sections = $self->getSections($project_id,$suite_id);
     return -500 if !$sections || (reftype($sections) || 'undef') ne 'ARRAY';
     foreach my $sec (@$sections) {
@@ -731,6 +758,7 @@ sub getCaseTypeByName {
     #Useful for marking automated tests, etc
     my ($self,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Case type must be string") unless $self->_checkString($name);
     my $types = $self->getCaseTypes();
     return -500 if !$types || (reftype($types) || 'undef') ne 'ARRAY';
     foreach my $type (@$types) {
@@ -779,6 +807,11 @@ Returns new case definition HASHREF, false otherwise.
 sub createCase {
     my ($self,$section_id,$title,$type_id,$opts,$extras) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Section ID ($section_id) must be integer") unless $self->_checkInteger($section_id);
+    confess("title must be string") unless $self->_checkString($title);
+    confess("Type ID must be integer") unless $self->_checkInteger($type_id);
+    confess("Options must be HASHREF") unless !defined($opts) || (reftype($opts) || 'undef') ne 'HASH';
+    confess("Extras must be HASHREF") unless !defined($extras) || (reftype($extras) || 'undef') ne 'HASH';
 
     my $stuff = {
         title   => $title,
@@ -823,6 +856,7 @@ Returns BOOLEAN.
 sub deleteCase {
     my ($self,$case_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Case ID must be integer") unless $self->_checkInteger($case_id);
     my $result = $self->_doRequest("index.php?/api/v2/delete_case/$case_id",'POST');
     return $result;
 }
@@ -850,6 +884,8 @@ Returns ARRAYREF of test case definition HASHREFs.
 sub getCases {
     my ($self,$project_id,$suite_id,$section_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
     my $url = "index.php?/api/v2/get_cases/$project_id&suite_id=$suite_id";
     $url .= "&section_id=$section_id" if $section_id;
     return $self->_doRequest($url);
@@ -880,6 +916,10 @@ Returns test case definition HASHREF.
 sub getCaseByName {
     my ($self,$project_id,$suite_id,$section_id,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
+    confess("Section ID must be integer") unless $self->_checkInteger($section_id);
+    confess("Test Case name must be string") unless $self->_checkString($name);
     my $cases = $self->getCases($project_id,$suite_id,$section_id);
     return -500 if !$cases || (reftype($cases) || 'undef') ne 'ARRAY';
     foreach my $case (@$cases) {
@@ -907,12 +947,13 @@ Returns test case definition HASHREF.
 sub getCaseByID {
     my ($self,$case_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Case ID must be integer") unless $self->_checkInteger($case_id);
     return $self->_doRequest("index.php?/api/v2/get_case/$case_id");
 }
 
 =head1 RUN METHODS
 
-=head2 B<createRun (project_id)>
+=head2 B<createRun (project_id,suite_id,name,description,milestone_id,assigned_to_id,case_ids)>
 
 Create a run.
 
@@ -926,9 +967,9 @@ Create a run.
 
 =item STRING C<DESCRIPTION> (optional) - Description of run
 
-=item INTEGER C<MILESTONE_ID> (optional) - ID of milestone
+=item INTEGER C<MILESTONE ID> (optional) - ID of milestone
 
-=item INTEGER C<ASSIGNED_TO_ID> (optional) - User to assign the run to
+=item INTEGER C<ASSIGNED TO ID> (optional) - User to assign the run to
 
 =item ARRAYREF C<CASE IDS> (optional) - Array of case IDs in case you don't want to use the whole testsuite when making the build.
 
@@ -944,6 +985,13 @@ Returns run definition HASHREF.
 sub createRun {
     my ($self,$project_id,$suite_id,$name,$desc,$milestone_id,$assignedto_id,$case_ids) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Suite ID must be integer") unless $self->_checkInteger($suite_id);
+    confess("Name must be string") unless $self->_checkString($name);
+    confess("Description must be string") unless !defined($desc) || $self->_checkString($desc);
+    confess("Milestone ID must be integer") unless !defined($milestone_id) || $self->_checkInteger($milestone_id);
+    confess("Assigned To ID must be integer") unless !defined($assignedto_id) || $self->_checkInteger($assignedto_id);
+    confess("Case IDs must be ARRAYREF") unless !defined($case_ids) || (reftype($case_ids) || 'undef') eq 'ARRAY';
 
     my $stuff = {
         suite_id      => $suite_id,
@@ -976,9 +1024,10 @@ Returns BOOLEAN.
 =cut
 
 sub deleteRun {
-    my ($self,$suite_id) = @_;
+    my ($self,$run_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
-    my $result = $self->_doRequest("index.php?/api/v2/delete_run/$suite_id",'POST');
+    confess("Run ID must be integer") unless $self->_checkInteger($run_id);
+    my $result = $self->_doRequest("index.php?/api/v2/delete_run/$run_id",'POST');
     return $result;
 }
 
@@ -1001,6 +1050,7 @@ Returns ARRAYREF of run definition HASHREFs.
 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");
 }
 
@@ -1026,6 +1076,8 @@ Returns run definition HASHREF.
 sub getRunByName {
     my ($self,$project_id,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Run name must be string") unless $self->_checkString($name);
     my $runs = $self->getRuns($project_id);
     return -500 if !$runs || (reftype($runs) || 'undef') ne 'ARRAY';
     foreach my $run (@$runs) {
@@ -1053,6 +1105,7 @@ Returns run definition HASHREF.
 sub getRunByID {
     my ($self,$run_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Run ID must be integer") unless $self->_checkInteger($run_id);
     return $self->_doRequest("index.php?/api/v2/get_run/$run_id");
 }
 
@@ -1060,7 +1113,7 @@ sub getRunByID {
 
 =head2 B<createPlan (project_id,name,description,milestone_id,entries)>
 
-Create a run.
+Create a test plan.
 
 =over 4
 
@@ -1091,6 +1144,11 @@ Returns test plan definition HASHREF, or false on failure.
 sub createPlan {
     my ($self,$project_id,$name,$desc,$milestone_id,$entries) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Plan name must be string") unless $self->_checkString($name);
+    confess("Description must be string") unless !defined($desc) || $self->_checkString($desc);
+    confess("Milestone ID must be integer") unless !defined($milestone_id) || $self->_checkInteger($milestone_id);
+    confess("Entries must be ARRAYREF") unless !defined($entries) || (reftype($entries) || 'undef') eq 'ARRAY';
 
     my $stuff = {
         name          => $name,
@@ -1122,6 +1180,7 @@ Returns BOOLEAN.
 sub deletePlan {
     my ($self,$plan_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Plan ID must be integer") unless $self->_checkInteger($plan_id);
     my $result = $self->_doRequest("index.php?/api/v2/delete_plan/$plan_id",'POST');
     return $result;
 }
@@ -1145,6 +1204,7 @@ Returns ARRAYREF of plan definition HASHREFs.
 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");
 }
 
@@ -1169,6 +1229,8 @@ Returns plan definition HASHREF.
 sub getPlanByName {
     my ($self,$project_id,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Plan name must be string") unless $self->_checkString($name);
     my $plans = $self->getPlans($project_id);
     return -500 if !$plans || (reftype($plans) || 'undef') ne 'ARRAY';
     foreach my $plan (@$plans) {
@@ -1196,6 +1258,7 @@ Returns plan definition HASHREF.
 sub getPlanByID {
     my ($self,$plan_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Plan ID must be integer") unless $self->_checkInteger($plan_id);
     return $self->_doRequest("index.php?/api/v2/get_plan/$plan_id");
 }
 
@@ -1226,6 +1289,10 @@ Returns milestone definition HASHREF, or false on failure.
 sub createMilestone {
     my ($self,$project_id,$name,$desc,$due_on) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Name must be string") unless $self->_checkString($name);
+    confess("Description must be string") unless !defined($desc) || $self->_checkString($desc);
+    confess("Due on must be unix time stamp (integer)") unless !defined($due_on) || $self->_checkInteger($due_on);
 
     my $stuff = {
         name        => $name,
@@ -1256,6 +1323,7 @@ Returns BOOLEAN.
 sub deleteMilestone {
     my ($self,$milestone_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Milestone ID must be integer") unless $self->_checkInteger($milestone_id);
     my $result = $self->_doRequest("index.php?/api/v2/delete_milestone/$milestone_id",'POST');
     return $result;
 }
@@ -1280,6 +1348,7 @@ Returns ARRAYREF of milestone definition HASHREFs.
 sub getMilestones {
     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_milestones/$project_id");
 }
 
@@ -1304,6 +1373,8 @@ Returns milestone definition HASHREF.
 sub getMilestoneByName {
     my ($self,$project_id,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Project ID must be integer") unless $self->_checkInteger($project_id);
+    confess("Milestone name must be string") unless $self->_checkString($name);
     my $milestones = $self->getMilestones($project_id);
     return -500 if !$milestones || (reftype($milestones) || 'undef') ne 'ARRAY';
     foreach my $milestone (@$milestones) {
@@ -1331,6 +1402,7 @@ Returns milestone definition HASHREF.
 sub getMilestoneByID {
     my ($self,$milestone_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Milestone ID must be integer") unless $self->_checkInteger($milestone_id);
     return $self->_doRequest("index.php?/api/v2/get_milestone/$milestone_id");
 }
 
@@ -1355,6 +1427,7 @@ Returns ARRAYREF of test definition HASHREFs.
 sub getTests {
     my ($self,$run_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Run ID must be integer") unless $self->_checkInteger($run_id);
     return $self->_doRequest("index.php?/api/v2/get_tests/$run_id");
 }
 
@@ -1379,6 +1452,8 @@ Returns test definition HASHREF.
 sub getTestByName {
     my ($self,$run_id,$name) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Run ID must be integer") unless $self->_checkInteger($run_id);
+    confess("Test name must be string") unless $self->_checkString($name);
     my $tests = $self->getTests($run_id);
     return -500 if !$tests || (reftype($tests) || 'undef') ne 'ARRAY';
     foreach my $test (@$tests) {
@@ -1406,6 +1481,7 @@ Returns test definition HASHREF.
 sub getTestByID {
     my ($self,$test_id) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Test ID must be integer") unless $self->_checkInteger($test_id);
     return $self->_doRequest("index.php?/api/v2/get_test/$test_id");
 }
 
@@ -1441,6 +1517,20 @@ sub getPossibleTestStatuses {
 
 Creates a result entry for a test.
 
+=over 4
+
+=item INTEGER C<TEST_ID> - ID of desired test
+
+=item INTEGER C<STATUS_ID> - ID of desired test result status
+
+=item STRING C<COMMENT> (optional) - Any comments about this result
+
+=item HASHREF C<OPTIONS> (optional) - Various "Baked-In" options that can be set for test results.  See TR docs for more information.
+
+=item HASHREF C<CUSTOM OPTIONS> (optional) - Options to set for custom fields.  See L<TestRail::API::buildStepResults> for a simple way to post up custom steps.
+
+=back
+
 Returns result definition HASHREF.
 
     $options = {
@@ -1473,6 +1563,11 @@ Returns result definition HASHREF.
 sub createTestResults {
     my ($self,$test_id,$status_id,$comment,$opts,$custom_fields) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Test ID must be integer") unless $self->_checkInteger($test_id);
+    confess("Status ID must be integer") unless $self->_checkInteger($status_id);
+    confess("Comment must be string") unless !defined($comment) || $self->_checkString($comment);
+    confess("Options must be HASHREF") unless !defined($opts) || (reftype($opts) || 'undef') eq 'HASH';
+    confess("Custom Options must be HASHREF") unless !defined($custom_fields) || (reftype($custom_fields) || 'undef') eq 'HASH';
     my $stuff = {
         status_id     => $status_id,
         comment       => $comment
@@ -1515,6 +1610,8 @@ Returns ARRAYREF of result definition HASHREFs.
 sub getTestResults {
     my ($self,$test_id,$limit) = @_;
     confess("Object methods must be called by an instance") unless ref($self);
+    confess("Test ID must be positive integer") unless $self->_checkInteger($test_id);
+    confess("Result limitation must be positive integer") unless $self->_checkInteger($limit) && $limit > 0;
     my $url = "index.php?/api/v2/get_results/$test_id";
     $url .= "&limit=$limit" if defined($limit);
     return $self->_doRequest($url);
@@ -1525,6 +1622,17 @@ sub getTestResults {
 =head2 B<buildStepResults(content,expected,actual,status_id)>
 
 Convenience method to build the stepResult hashes seen in the custom options for getTestResults.
+=over 4
+
+=item STRING C<CONTENT> (optional) - The step itself.
+
+=item STRING C<EXPECTED> (optional) - Expected result of test step.
+
+=item STRING C<ACTUAL> (optional) - Actual result of test step
+
+=item INTEGER C<STATUS ID> (optional) - Status ID of result
+
+=back
 
 =cut
 
@@ -1539,6 +1647,21 @@ sub buildStepResults {
     };
 }
 
+
+#Type checks
+
+sub _checkInteger {
+    shift;
+    my $integer = shift;
+    return ( defined $integer && looks_like_number($integer) && int($integer) == $integer );
+}
+
+sub _checkString {
+  shift;
+  my $str = shift;
+  return ( defined($str) && !ref($str) );
+}
+
 1;
 
 __END__

+ 64 - 0
t/arg_types.t

@@ -0,0 +1,64 @@
+use strict;
+use warnings;
+
+use TestRail::API;
+use Test::More 'tests' => 48;
+use Test::Fatal;
+use Class::Inspector;
+use Test::LWP::UserAgent;
+use HTTP::Response;
+
+my $tr = TestRail::API->new('http://hokum.bogus','bogus','bogus',1);
+$tr->{'browser'} = Test::LWP::UserAgent->new();
+$tr->{'browser'}->map_response(qr/.*/, HTTP::Response->new('500', 'ERROR', ['Content-Type' => 'text/plain'], ''));
+
+is( exception {$tr->getCaseTypes() },undef,'getCaseTypes returns no error when no arguments are passed');
+is( exception {$tr->getPossibleTestStatuses() },undef,'getPossibleTestStatuses returns no error when no arguments are passed');
+is( exception {$tr->getProjects() },undef,'getProjects returns no error when no arguments are passed');
+is( exception {$tr->getTestResultFields() },undef,'getTestResultFields returns no error when no arguments are passed');
+is( exception {$tr->getUsers() },undef,'getUsers returns no error when no arguments are passed');
+
+isnt( exception {$tr->createCase() },undef,'createCase returns error when no arguments are passed');
+isnt( exception {$tr->createMilestone() },undef,'createMilestone returns error when no arguments are passed');
+isnt( exception {$tr->createPlan() },undef,'createPlan returns error when no arguments are passed');
+isnt( exception {$tr->createProject() },undef,'createProject returns error when no arguments are passed');
+isnt( exception {$tr->createRun() },undef,'createRun returns error when no arguments are passed');
+isnt( exception {$tr->createSection() },undef,'createSection returns error when no arguments are passed');
+isnt( exception {$tr->createTestResults() },undef,'createTestResults returns error when no arguments are passed');
+isnt( exception {$tr->createTestSuite() },undef,'createTestSuite returns error when no arguments are passed');
+isnt( exception {$tr->deleteCase() },undef,'deleteCase returns error when no arguments are passed');
+isnt( exception {$tr->deleteMilestone() },undef,'deleteMilestone returns error when no arguments are passed');
+isnt( exception {$tr->deletePlan() },undef,'deletePlan returns error when no arguments are passed');
+isnt( exception {$tr->deleteProject() },undef,'deleteProject returns error when no arguments are passed');
+isnt( exception {$tr->deleteRun() },undef,'deleteRun returns error when no arguments are passed');
+isnt( exception {$tr->deleteSection() },undef,'deleteSection returns error when no arguments are passed');
+isnt( exception {$tr->deleteTestSuite() },undef,'deleteTestSuite returns error when no arguments are passed');
+isnt( exception {$tr->getCaseByID() },undef,'getCaseByID returns error when no arguments are passed');
+isnt( exception {$tr->getCaseByName() },undef,'getCaseByName returns error when no arguments are passed');
+isnt( exception {$tr->getCaseTypeByName() },undef,'getCaseTypeByName returns error when no arguments are passed');
+isnt( exception {$tr->getCases() },undef,'getCases returns error when no arguments are passed');
+isnt( exception {$tr->getMilestoneByID() },undef,'getMilestoneByID returns error when no arguments are passed');
+isnt( exception {$tr->getMilestoneByName() },undef,'getMilestoneByName returns error when no arguments are passed');
+isnt( exception {$tr->getPlanByID() },undef,'getPlanByID returns error when no arguments are passed');
+isnt( exception {$tr->getPlanByName() },undef,'getPlanByName returns error when no arguments are passed');
+isnt( exception {$tr->getProjectByID() },undef,'getProjectByID returns error when no arguments are passed');
+isnt( exception {$tr->getProjectByName() },undef,'getProjectByName returns error when no arguments are passed');
+isnt( exception {$tr->getRunByID() },undef,'getRunByID returns error when no arguments are passed');
+isnt( exception {$tr->getRunByName() },undef,'getRunByName returns error when no arguments are passed');
+isnt( exception {$tr->getSectionByID() },undef,'getSectionByID returns error when no arguments are passed');
+isnt( exception {$tr->getSectionByName() },undef,'getSectionByName returns error when no arguments are passed');
+isnt( exception {$tr->getTestByID() },undef,'getTestByID returns error when no arguments are passed');
+isnt( exception {$tr->getTestByName() },undef,'getTestByName returns error when no arguments are passed');
+isnt( exception {$tr->getTestResults() },undef,'getTestResults returns error when no arguments are passed');
+isnt( exception {$tr->getTestSuiteByID() },undef,'getTestSuiteByID returns error when no arguments are passed');
+isnt( exception {$tr->getTestSuiteByName() },undef,'getTestSuiteByName returns error when no arguments are passed');
+isnt( exception {$tr->getUserByEmail() },0,'getUserByEmail returns error when no arguments are passed');
+isnt( exception {$tr->getUserByID() },0,'getUserByID returns error when no arguments are passed');
+isnt( exception {$tr->getUserByName() },0,'getUserByName returns error when no arguments are passed');
+isnt( exception {$tr->getTests() },undef,'getTests returns error when no arguments are passed');
+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->getPlans() },undef,'getPlans returns error when no arguments are passed');
+isnt( exception {$tr->getMilestones() },undef,'getMilestones returns error when no arguments are passed');
+

+ 1 - 1
t/author-classSafety.t

@@ -21,7 +21,7 @@ foreach my $module (@excludeModules) {
 }
 
 foreach my $method (@{$methods[0]}) {
-    next if grep {$method eq $_} qw{new buildStepResults};
+    next if grep {$method eq $_} qw{new buildStepResults _checkInteger _checkString};
     next if grep {$_ eq $method} @excludedMethods;
     like( exception {TestRail::API->$method}, qr/.*called by an instance.*/ , "Calling $method requires an instance");
 }

+ 45 - 42
t/server_dead.t

@@ -8,60 +8,63 @@ use TestRail::API;
 use Test::More 'tests' => 51;
 use Test::Fatal;
 use Class::Inspector;
+use Test::LWP::UserAgent;
+use HTTP::Response;
 
 my $tr = TestRail::API->new('http://hokum.bogus','bogus','bogus',1);
+$tr->{'browser'} = Test::LWP::UserAgent->new();
+$tr->{'browser'}->map_response(qr/.*/, HTTP::Response->new('500', 'ERROR', ['Content-Type' => 'text/plain'], ''));
 
-note $tr->_doRequest('badMethod');
 is( $tr->_doRequest('badMethod'), -500,"Bad Request fails");
 
 is($tr->apiurl,'http://hokum.bogus',"APIURL OK");
 is($tr->debug,1,"DEBUG OK");
 
-is($tr->createCase(),-500,'createCase returns error');
-is($tr->createMilestone(),-500,'createMilestone returns error');
-is($tr->createPlan(),-500,'createPlan returns error');
-is($tr->createProject(),-500,'createProject returns error');
-is($tr->createRun(),-500,'createRun returns error');
-is($tr->createSection(),-500,'createSection returns error');
-is($tr->createTestResults(),-500,'createTestResults returns error');
-is($tr->createTestSuite(),-500,'createTestSuite returns error');
-is($tr->deleteCase(),-500,'deleteCase returns error');
-is($tr->deleteMilestone(),-500,'deleteMilestone returns error');
-is($tr->deletePlan(),-500,'deletePlan returns error');
-is($tr->deleteProject(),-500,'deleteProject returns error');
-is($tr->deleteRun(),-500,'deleteRun returns error');
-is($tr->deleteSection(),-500,'deleteSection returns error');
-is($tr->deleteTestSuite(),-500,'deleteTestSuite returns error');
-is($tr->getCaseByID(),-500,'getCaseByID returns error');
-is($tr->getCaseByName(),-500,'getCaseByName returns error');
-is($tr->getCaseTypeByName(),-500,'getCaseTypeByName returns error');
+is($tr->createCase(1,'whee',1),-500,'createCase returns error');
+is($tr->createMilestone(1,'whee'),-500,'createMilestone returns error');
+is($tr->createPlan(1,'whee'),-500,'createPlan returns error');
+is($tr->createProject('zippy'),-500,'createProject returns error');
+is($tr->createRun(1,1,'whee'),-500,'createRun returns error');
+is($tr->createSection(1,1,'whee'),-500,'createSection returns error');
+is($tr->createTestResults(1,1),-500,'createTestResults returns error');
+is($tr->createTestSuite(1,'zugzug'),-500,'createTestSuite returns error');
+is($tr->deleteCase(1),-500,'deleteCase returns error');
+is($tr->deleteMilestone(1),-500,'deleteMilestone returns error');
+is($tr->deletePlan(1),-500,'deletePlan returns error');
+is($tr->deleteProject(1),-500,'deleteProject returns error');
+is($tr->deleteRun(1),-500,'deleteRun returns error');
+is($tr->deleteSection(1),-500,'deleteSection returns error');
+is($tr->deleteTestSuite(1),-500,'deleteTestSuite returns error');
+is($tr->getCaseByID(1),-500,'getCaseByID returns error');
+is($tr->getCaseByName(1,1,1,'hug'),-500,'getCaseByName returns error');
+is($tr->getCaseTypeByName('zap'),-500,'getCaseTypeByName returns error');
 is($tr->getCaseTypes(),-500,'getCaseTypes returns error');
-is($tr->getCases(),-500,'getCases returns error');
-is($tr->getMilestoneByID(),-500,'getMilestoneByID returns error');
-is($tr->getMilestoneByName(),-500,'getMilestoneByName returns error');
-is($tr->getMilestones(),-500,'getMilestones returns error');
-is($tr->getPlanByID(),-500,'getPlanByID returns error');
-is($tr->getPlanByName(),-500,'getPlanByName returns error');
-is($tr->getPlans(),-500,'getPlans returns error');
+is($tr->getCases(1,2,3),-500,'getCases returns error');
+is($tr->getMilestoneByID(1,1),-500,'getMilestoneByID returns error');
+is($tr->getMilestoneByName(1,'hug'),-500,'getMilestoneByName returns error');
+is($tr->getMilestones(1),-500,'getMilestones returns error');
+is($tr->getPlanByID(1),-500,'getPlanByID returns error');
+is($tr->getPlanByName(1,'nugs'),-500,'getPlanByName returns error');
+is($tr->getPlans(1),-500,'getPlans returns error');
 is($tr->getPossibleTestStatuses(),-500,'getPossibleTestStatuses returns error');
 is($tr->getProjectByID(1),-500,'getProjectByID returns error');
 is($tr->getProjectByName('fake'),-500,'getProjectByName returns error');
 is($tr->getProjects(),-500,'getProjects returns error');
-is($tr->getRunByID(),-500,'getRunByID returns error');
-is($tr->getRunByName(),-500,'getRunByName returns error');
-is($tr->getRuns(),-500,'getRuns returns error');
-is($tr->getSectionByID(),-500,'getSectionByID returns error');
-is($tr->getSectionByName(),-500,'getSectionByName returns error');
-is($tr->getSections(),-500,'getSections returns error');
-is($tr->getTestByID(),-500,'getTestByID returns error');
-is($tr->getTestByName(),-500,'getTestByName returns error');
+is($tr->getRunByID(1),-500,'getRunByID returns error');
+is($tr->getRunByName(1,'zoom'),-500,'getRunByName returns error');
+is($tr->getRuns(1),-500,'getRuns returns error');
+is($tr->getSectionByID(1),-500,'getSectionByID returns error');
+is($tr->getSectionByName(1,1,'zip'),-500,'getSectionByName returns error');
+is($tr->getSections(1,1),-500,'getSections returns error');
+is($tr->getTestByID(1),-500,'getTestByID returns error');
+is($tr->getTestByName(1,'poo'),-500,'getTestByName returns error');
 is($tr->getTestResultFields(),-500,'getTestResultFields returns error');
-is($tr->getTestResults(),-500,'getTestResults returns error');
-is($tr->getTestSuiteByID(),-500,'getTestSuiteByID returns error');
-is($tr->getTestSuiteByName(),-500,'getTestSuiteByName returns error');
-is($tr->getTestSuites(),-500,'getTestSuites returns error');
-is($tr->getTests(),-500,'getTests returns error');
-is($tr->getUserByEmail(),0,'getUserByEmail returns error');
-is($tr->getUserByID(),0,'getUserByID returns error');
-is($tr->getUserByName(),0,'getUserByName returns error');
+is($tr->getTestResults(1,1),-500,'getTestResults returns error');
+is($tr->getTestSuiteByID(1),-500,'getTestSuiteByID returns error');
+is($tr->getTestSuiteByName(1,'zap'),-500,'getTestSuiteByName returns error');
+is($tr->getTestSuites(1),-500,'getTestSuites returns error');
+is($tr->getTests(1),-500,'getTests returns error');
+is($tr->getUserByEmail('tickle'),0,'getUserByEmail returns error');
+is($tr->getUserByID(1),0,'getUserByID returns error');
+is($tr->getUserByName('zap'),0,'getUserByName returns error');
 is($tr->getUsers(),-500,'getUsers returns error');