testrail-report 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #!/usr/bin/env perl
  2. # ABSTRACT: Upload your TAP results to TestRail after they've finished
  3. # PODNAME: TestRail::Bin::Report
  4. =head1 SYNOPSIS
  5. testrail-report [OPTIONS] tapfile
  6. prove -v sometest.t > results.tap && testrail-report [OPTIONS] results.tap
  7. prove -v sometest.t | testrail-report [OPTIONS]
  8. prove -PTestRail='apiurl=http://some.testlink.install/,user=someUser,password=somePassword,project=TestProject,run=TestRun,plan=TestPlan,configs=Config1:Config2:Config3,version=0.014' sometest.t
  9. require `which testrail-report`;
  10. TestRail::Bin::Report::run(@args);
  11. =head1 DESCRIPTION
  12. testrail-report - report raw TAP results to a TestRail install
  13. Can be used as the modulino TestRail::Bin::Report.
  14. =head2 PARAMETERS:
  15. =head3 MANDATORY PARAMETERS
  16. --project [someproject] : associate results (if any) with theprovided project name.
  17. --run [somerun] : associates results (if any) with the provided run name.
  18. IF none of these options are provided, you will be asked to type
  19. these in as needed, supposing you are not redirecting input
  20. (such as piping into this command).
  21. =head3 SEMI-OPTIONAL PARAMETERS
  22. --plan [someplan] : look for the provided run name within the provided plan.
  23. --config [someconfig] : filter run by the provided configuration.
  24. This option can be passed multiple times for detailed filtering.
  25. -e --encoding: Character encoding of arguments. Defaults to UTF-8.
  26. See L<Encode::Supported> for supported encodings.
  27. Test plans can have runs with the same name, but different configurations, which is understandably confusing.
  28. You can do the same outside of plans, and without configurations; but doing so is ill advised, and the only option from there is to use IDs.
  29. So, try not to do that if you want to use this tool, and want sanity in your Test management system.
  30. The way around this is to specify what plan and configuration you want to set results for.
  31. This should provide sufficient uniqueness to get any run using names.
  32. =head3 OPTIONAL PARAMETERS
  33. --testsuite_id [testsuite_id] : Attempt to create a run based on the provided testsuite ID. Uses the name provided with --run.
  34. If plans/configurations are supplied, it will attempt to create it as a child of the provided plan, and with the supplied configurations.
  35. If the specified run already exists, the program will simply use the existing run, and disregard the supplied testsuite_id.
  36. If the specified plan does not exist, it too will be created for you.
  37. --testsuite [testsuite name] : Pretty much the same as the testsuite_id, but a name instead. Mutually exclusive with testsuite_id.
  38. --section [section_name] : When spawning, restrict the cases used in the provided testsuite ID to these sections.
  39. Option may be passed multiple times to specify multiple sections.
  40. =head3 CONFIG OPTIONS
  41. In your $HOME (or the current directory, if your system has no concept of a home directory), put a file called .testrailrc with key=value
  42. syntax separated by newlines. Valid Keys are: apiurl,user,password
  43. =head3 CONFIG OVERRIDES
  44. These override the config, if present. If neither are used, you will be prompted.
  45. --apiurl [url] : full URL to get to TestRail index document
  46. --password [key] : Your TestRail Password or a valid API key (TestRail 4.2 and above).
  47. --user [name] : Your TestRail User Name.
  48. =head3 BEHAVIOR
  49. --case-ok : Whether to consider each OK to correspond to a test in TestRail
  50. --step-results [name] : 'System Name' of a 'step_results' type field to set for your tests.
  51. These options are mutually exclusive. If neither is set, the
  52. overall result of the test will be used as the pass/fail for the test.
  53. =head3 RESULT OPTIONS
  54. --version : String describing the version of the system under test.
  55. --autoclose : If there are no more tests in 'untested' or 'retest' status for the specified run/plan, close it.
  56. =head2 PROVE PLUGIN:
  57. passing -PTestRail='key=value,...' to prove will
  58. automatically upload your test results while the test is running if
  59. real-time results are desired.
  60. See L<App::Prove::Plugin::TestRail> for more information.
  61. =head2 REQUIREMENTS:
  62. Your TestRail install must have 3 custom statuses with the internal
  63. names 'skip', 'todo_pass', and 'todo_fail', to represent those
  64. states which TAP can have.
  65. Also, be sure your tests don't output non-TAP (unknown) lines ending in dots (.)
  66. This will cause the preceding characters to be interpreted as a test name, which may lead to unexpected results.
  67. =cut
  68. package TestRail::Bin::Report;
  69. use strict;
  70. use warnings;
  71. use TestRail::Utils;
  72. use Getopt::Long qw{GetOptionsFromArray};
  73. use Test::Rail::Parser;
  74. use File::HomeDir qw{my_home};
  75. if (!caller()) {
  76. my ($out,$code) = run(@ARGV);
  77. print $out;
  78. exit $code;
  79. }
  80. #Main loop------------
  81. sub run {
  82. my $args = \@_;
  83. my %opts;
  84. print "testrail-report\n----------------------\n";
  85. #parse switches
  86. GetOptionsFromArray($args,
  87. 'run=s' => \$opts{run},
  88. 'apiurl=s' => \$opts{apiurl},
  89. 'password=s' => \$opts{password},
  90. 'user=s' => \$opts{user},
  91. 'project=s' => \$opts{project},
  92. 'case-ok' => \$opts{case_per_ok},
  93. 'step-results=s' => \$opts{step_results},
  94. 'config=s@' => \$opts{configs},
  95. 'plan=s' => \$opts{plan},
  96. 'version=s' => \$opts{version},
  97. 'testsuite_id=i' => \$opts{testsuite_id},
  98. 'testsuite=s' => \$opts{testsuite},
  99. 'section=s@' => \$opts{sections},
  100. 'autoclose' => \$opts{autoclose},
  101. 'e|encoding=s' => \$opts{encoding},
  102. 'help' => \$opts{help},
  103. 'mock' => \$opts{mock}
  104. );
  105. if ($opts{help}) { return ('',TestRail::Utils::help()); }
  106. #Parse config file if we are missing api url/key or user
  107. my $homedir = my_home() || '.';
  108. if (-e $homedir . '/.testrailrc' && (!$opts{apiurl} || !$opts{password} || !$opts{user}) ) {
  109. ($opts{apiurl},$opts{password},$opts{user}) = TestRail::Utils::parseConfig($homedir,1);
  110. }
  111. #If argument is passed use it instead of stdin
  112. my $file = $args->[0];
  113. die "No Such File $file" if ($file && !-e $file);
  114. die "ERROR: Interactive mode not allowed when piping input. See --help for options." if ( !$opts{run} || !$opts{apiurl} || !$opts{password} || !$opts{user} || !$opts{project} );
  115. my @files = TestRail::Utils::TAP2TestFiles($file);
  116. TestRail::Utils::interrogateUser(\%opts,qw{apiurl user password project run});
  117. $opts{result_options} = {'version' => $opts{version}} if $opts{version};
  118. if ($opts{'mock'}) {
  119. require 't/lib/Test/LWP/UserAgent/TestRailMock.pm'; ## no critic
  120. $opts{'browser'} = $Test::LWP::UserAgent::TestRailMock::mockObject;
  121. $opts{'debug'} = 1;
  122. }
  123. my $tap;
  124. foreach my $phil (@files) {
  125. $tap = Test::Rail::Parser->new({
  126. 'tap' => $phil,
  127. 'apiurl' => $opts{apiurl},
  128. 'user' => $opts{user},
  129. 'pass' => $opts{password},
  130. 'run' => $opts{run},
  131. 'project' => $opts{project},
  132. 'case_per_ok' => $opts{case_per_ok},
  133. 'step_results' => $opts{step_results},
  134. 'debug' => $opts{debug},
  135. 'browser' => $opts{browser},
  136. 'plan' => $opts{plan},
  137. 'configs' => $opts{configs},
  138. 'result_options' => $opts{result_options},
  139. 'testsuite_id' => $opts{testsuite_id},
  140. 'testsuite' => $opts{testsuite},
  141. 'sections' => $opts{sections},
  142. 'autoclose' => $opts{autoclose},
  143. 'encoding' => $opts{encoding},
  144. 'merge' => 1
  145. });
  146. $tap->run();
  147. }
  148. #all done
  149. return ("Done.\n",0);
  150. }
  151. 1;
  152. __END__
  153. =head1 SEE ALSO
  154. L<TestRail::API>
  155. L<App::Prove::Plugin::TestRail>
  156. L<TAP::Parser>
  157. L<File::HomeDir> for the finding of .testrailrc
  158. =head1 SPECIAL THANKS
  159. Thanks to cPanel Inc, for graciously funding the creation of this distribution.