Test-Rail-Parser.t 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use FindBin;
  5. use lib "$FindBin::Bin/lib";
  6. use Scalar::Util qw{reftype};
  7. use TestRail::API;
  8. use Test::LWP::UserAgent::TestRailMock;
  9. use Test::Rail::Parser;
  10. use Test::More 'tests' => 115;
  11. use Test::Fatal qw{exception};
  12. use Test::Deep qw{cmp_deeply};
  13. #Same song and dance as in TestRail-API.t
  14. my $apiurl = $ENV{'TESTRAIL_API_URL'};
  15. my $login = $ENV{'TESTRAIL_USER'};
  16. my $pw = $ENV{'TESTRAIL_PASSWORD'};
  17. my $is_mock = (!$apiurl && !$login && !$pw);
  18. ($apiurl,$login,$pw) = ('http://testrail.local','teodesian@cpan.org','fake') if $is_mock;
  19. my ($debug,$browser);
  20. $debug = 1;
  21. if ($is_mock) {
  22. $browser = $Test::LWP::UserAgent::TestRailMock::mockObject;
  23. }
  24. #test exceptions...
  25. #TODO
  26. my $fcontents = "
  27. fake.test ..
  28. 1..2
  29. ok 1 - STORAGE TANKS SEARED
  30. #goo
  31. not ok 2 - NOT SO SEARED AFTER ARR
  32. ";
  33. my $tap;
  34. my $opts = {
  35. 'tap' => $fcontents,
  36. 'apiurl' => $apiurl,
  37. 'user' => $login,
  38. 'pass' => $pw,
  39. 'debug' => $debug,
  40. 'browser' => $browser,
  41. 'run' => 'TestingSuite',
  42. 'project' => 'TestProject',
  43. 'merge' => 1,
  44. };
  45. my $res = exception { $tap = Test::Rail::Parser->new($opts) };
  46. is($res,undef,"TR Parser doesn't explode on instantiation");
  47. isa_ok($tap,"Test::Rail::Parser");
  48. if (!$res) {
  49. $tap->run();
  50. is($tap->{'errors'},0,"No errors encountered uploading case results");
  51. }
  52. undef $tap;
  53. delete $opts->{'tap'};
  54. $opts->{'source'} = 't/fake.test';
  55. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  56. is($res,undef,"TR Parser doesn't explode on instantiation");
  57. isa_ok($tap,"Test::Rail::Parser");
  58. if (!$res) {
  59. $tap->run();
  60. is($tap->{'errors'},0,"No errors encountered uploading case results");
  61. }
  62. $fcontents = "fake.test...
  63. ok 1 - STORAGE TANKS SEARED
  64. # whee
  65. not ok 2 - NOT SO SEARED AFTER ARR
  66. # Failed test 'NOT SO SEARED AFTER ARR'
  67. # at t/fake.test line 10.
  68. # Looks like you failed 1 test of 2.
  69. ";
  70. like($tap->{'raw_output'},qr/SEARED\n# whee.*\n.*AFTER ARR\n\n.*Failed/msxi,"Full raw content uploaded in non step results mode");
  71. #Check that time run is being uploaded
  72. my $timeResults = $tap->{'tr_opts'}->{'testrail'}->getTestResults(1);
  73. if ( ( reftype($timeResults) || 'undef') eq 'ARRAY') {
  74. is( $timeResults->[0]->{'elapsed'}, '2s', "Plugin correctly sets elapsed time");
  75. } else {
  76. fail("Could not get test results to check elapsed time!");
  77. }
  78. #Check the time formatting routine.
  79. is(Test::Rail::Parser::_compute_elapsed(0,0),undef,"Elapsed computation correct at second boundary");
  80. is(Test::Rail::Parser::_compute_elapsed(0,61),'1m 1s',"Elapsed computation correct at minute boundary");
  81. is(Test::Rail::Parser::_compute_elapsed(0,3661),'1h 1m 1s',"Elapsed computation correct at hour boundary");
  82. is(Test::Rail::Parser::_compute_elapsed(0,86461),'24h 1m 1s',"Elapsed computation correct at day boundary");
  83. undef $tap;
  84. $opts->{'source'} = 't/faker.test';
  85. $opts->{'run'} = 'OtherOtherSuite';
  86. $opts->{'step_results'} = 'step_results';
  87. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  88. is($res,undef,"TR Parser doesn't explode on instantiation");
  89. isa_ok($tap,"Test::Rail::Parser");
  90. if (!$res) {
  91. $tap->run();
  92. is($tap->{'errors'},0,"No errors encountered uploading case results");
  93. is($tap->{'global_status'},5, "Test global result is FAIL when one subtest fails even if there are TODO passes");
  94. subtest 'Timestamp/elapsed printed in step results' => sub {
  95. foreach my $result (@{$tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'}}) {
  96. like($result->{'content'}, qr/^\[.*\(.*\)\]/i, "Timestamp printed in step results");
  97. }
  98. };
  99. }
  100. #Default mode
  101. undef $tap;
  102. delete $opts->{'step_results'};
  103. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  104. is($res,undef,"TR Parser doesn't explode on instantiation");
  105. isa_ok($tap,"Test::Rail::Parser");
  106. if (!$res) {
  107. $tap->run();
  108. is($tap->{'errors'},0,"No errors encountered uploading case results");
  109. my @matches = $tap->{'raw_output'} =~ m/^(\[.*\(.*\)\])/msgi;
  110. ok(scalar(@matches),"Timestamps present in raw TAP");
  111. }
  112. #Default mode
  113. undef $tap;
  114. $fcontents = "
  115. fake.test ..
  116. 1..2
  117. ok 1 - STORAGE TANKS SEARED
  118. #Subtest NOT SO SEARED AFTER ARR
  119. ok 1 - STROGGIFY POPULATION CENTERS
  120. not ok 2 - STROGGIFY POPULATION CENTERS
  121. #goo
  122. not ok 2 - NOT SO SEARED AFTER ARR
  123. ";
  124. $opts->{'tap'} = $fcontents;
  125. delete $opts->{'source'};
  126. delete $opts->{'step_results'};
  127. $opts->{'run'} = 'TestingSuite';
  128. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  129. is($res,undef,"TR Parser doesn't explode on instantiation");
  130. isa_ok($tap,"Test::Rail::Parser");
  131. if (!$res) {
  132. $tap->run();
  133. is($tap->{'errors'},0,"No errors encountered uploading case results");
  134. }
  135. undef $tap;
  136. delete $opts->{'tap'};
  137. $opts->{'source'} = 't/skip.test';
  138. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  139. is($res,undef,"TR Parser doesn't explode on instantiation");
  140. isa_ok($tap,"Test::Rail::Parser");
  141. if (!$res) {
  142. $tap->run();
  143. is($tap->{'errors'},0,"No errors encountered uploading case results");
  144. }
  145. #Default mode skip (skip_all)
  146. undef $tap;
  147. $opts->{'source'} = 't/skipall.test';
  148. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  149. is($res,undef,"TR Parser doesn't explode on instantiation");
  150. isa_ok($tap,"Test::Rail::Parser");
  151. if (!$res) {
  152. $tap->run();
  153. is($tap->{'errors'},0,"No errors encountered uploading case results");
  154. is($tap->{'global_status'},6, "Test global result is SKIP on skip all");
  155. }
  156. #Ok, let's test the plan, config, and spawn bits.
  157. undef $tap;
  158. $opts->{'run'} = 'hoo hoo I do not exist';
  159. $opts->{'plan'} = 'mah dubz plan';
  160. $opts->{'configs'} = ['testPlatform1'];
  161. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  162. isnt($res,undef,"TR Parser explodes on instantiation when asking for run not in plan");
  163. undef $tap;
  164. $opts->{'run'} = 'TestingSuite';
  165. $opts->{'configs'} = ['testConfig'];
  166. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  167. is($res,undef,"TR Parser doesn't explode on instantiation looking for existing run in plan");
  168. isa_ok($tap,"Test::Rail::Parser");
  169. if (!$res) {
  170. $tap->run();
  171. is($tap->{'errors'},0,"No errors encountered uploading case results");
  172. }
  173. #Now, test spawning.
  174. undef $tap;
  175. $opts->{'run'} = 'TestingSuite2';
  176. $opts->{'configs'} = ['testPlatform1'];
  177. $opts->{'testsuite_id'} = 9;
  178. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  179. is($res,undef,"TR Parser doesn't explode on instantiation when spawning run in plan");
  180. isa_ok($tap,"Test::Rail::Parser");
  181. if (!$res) {
  182. $tap->run();
  183. is($tap->{'errors'},0,"No errors encountered uploading case results");
  184. }
  185. #Test spawning of builds not in plans.
  186. #Now, test spawning.
  187. undef $tap;
  188. delete $opts->{'testsuite_id'};
  189. delete $opts->{'plan'};
  190. delete $opts->{'configs'};
  191. $opts->{'testsuite'} = 'HAMBURGER-IZE HUMANITY';
  192. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  193. is($res,undef,"TR Parser doesn't explode on instantiation when spawning run in plan");
  194. isa_ok($tap,"Test::Rail::Parser");
  195. if (!$res) {
  196. $tap->run();
  197. is($tap->{'errors'},0,"No errors encountered uploading case results");
  198. }
  199. #Test spawning of plans and runs.
  200. undef $tap;
  201. $opts->{'run'} = 'BogoRun';
  202. $opts->{'plan'} = 'BogoPlan';
  203. $opts->{'testsuite_id'} = 9;
  204. delete $opts->{'testsuite'};
  205. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  206. is($res,undef,"TR Parser doesn't explode on instantiation when spawning run in plan");
  207. isa_ok($tap,"Test::Rail::Parser");
  208. if (!$res) {
  209. $tap->run();
  210. is($tap->{'errors'},0,"No errors encountered uploading case results");
  211. }
  212. #Check that per-section spawn works
  213. undef $tap;
  214. $opts->{'source'} = 't/fake.test';
  215. delete $opts->{'plan'};
  216. $opts->{'sections'} = ['fake.test'];
  217. delete $opts->{'step_results'};
  218. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  219. is($res,undef,"TR Parser doesn't explode on instantiation");
  220. isa_ok($tap,"Test::Rail::Parser");
  221. if (!$res) {
  222. $tap->run();
  223. is($tap->{'errors'},0,"No errors encountered uploading case results");
  224. }
  225. #Check that per-section spawn works
  226. undef $tap;
  227. $opts->{'plan'} = 'BogoPlan';
  228. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  229. is($res,undef,"TR Parser doesn't explode on instantiation");
  230. isa_ok($tap,"Test::Rail::Parser");
  231. if (!$res) {
  232. $tap->run();
  233. is($tap->{'errors'},0,"No errors encountered uploading case results");
  234. }
  235. undef $tap;
  236. $opts->{'sections'} = ['potzrebie'];
  237. delete $opts->{'plan'};
  238. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  239. isnt($res,undef,"TR Parser explodes on instantiation with invalid section");
  240. undef $tap;
  241. $opts->{'source'} = 't/notests.test';
  242. delete $opts->{'sections'};
  243. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  244. is($res,undef,"TR Parser doesn't explode on instantiation");
  245. isa_ok($tap,"Test::Rail::Parser");
  246. if (!$res) {
  247. $tap->run();
  248. is($tap->{'errors'},0,"No errors encountered uploading case results");
  249. is($tap->{'global_status'},4, "Test global result is RETEST on env fail");
  250. }
  251. undef $tap;
  252. $opts->{'source'} = 't/pass.test';
  253. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  254. is($res,undef,"TR Parser doesn't explode on instantiation");
  255. isa_ok($tap,"Test::Rail::Parser");
  256. if (!$res) {
  257. $tap->run();
  258. is($tap->{'errors'},0,"No errors encountered uploading case results");
  259. is($tap->{'global_status'},1, "Test global result is PASS on ok test");
  260. }
  261. undef $tap;
  262. $opts->{'source'} = 't/todo_pass.test';
  263. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  264. is($res,undef,"TR Parser doesn't explode on instantiation");
  265. isa_ok($tap,"Test::Rail::Parser");
  266. if (!$res) {
  267. $tap->run();
  268. is($tap->{'errors'},0,"No errors encountered uploading case results");
  269. is($tap->{'global_status'},8, "Test global result is TODO PASS on todo pass test");
  270. }
  271. undef $tap;
  272. $opts->{'step_results'} = 'bogus_garbage';
  273. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  274. like($res,qr/invalid step results/i,"Bogus step results name throws");
  275. undef $tap;
  276. $opts->{'source'} = 't/todo_pass_and_fail.test';
  277. $opts->{'step_results'} = 'step_results';
  278. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  279. is($res,undef,"TR Parser doesn't explode on instantiation");
  280. isa_ok($tap,"Test::Rail::Parser");
  281. if (!$res) {
  282. $tap->run();
  283. is($tap->{'errors'},1,"Errors encountered uploading case results for case that does not exist in TestRail");
  284. is($tap->{'global_status'},7, "Test global result is TODO FAIL on todo pass & fail test");
  285. my @desired_statuses = qw{1 8 7};
  286. my @got_statuses = map {$_->{'status_id'}} @{$tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'}};
  287. my @desired_expected = ('OK', 'OK', 'OK');
  288. my @got_expected = map {$_->{'expected'}} @{$tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'}};
  289. my @desired_actual = ('OK', 'TODO PASS', 'TODO FAIL');
  290. my @got_actual = map {$_->{'actual'}} @{$tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'}};
  291. cmp_deeply(\@got_expected,\@desired_expected,"Expected status names look OK");
  292. cmp_deeply(\@got_actual,\@desired_actual,"Actual status names look OK");
  293. cmp_deeply(\@got_statuses,\@desired_statuses,"Step result status codes set correctly");
  294. like($tap->{'tr_opts'}->{'test_notes'},qr/ez duz it/i,"TODO reason captured in test notes");
  295. }
  296. undef $opts->{'step_results'};
  297. undef $tap;
  298. #Check bad plan w/ todo pass logic
  299. $fcontents = "
  300. todo_pass.test ..
  301. 1..2
  302. ok 1 - STORAGE TANKS SEARED #TODO todo pass
  303. # goo
  304. ";
  305. undef $opts->{'source'};
  306. $opts->{'tap'} = $fcontents;
  307. $opts->{'step_results'} = 'step_results';
  308. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  309. is($res,undef,"TR Parser doesn't explode on instantiation");
  310. isa_ok($tap,"Test::Rail::Parser");
  311. if (!$res) {
  312. $tap->run();
  313. is($tap->{'errors'},0,"No errors encountered uploading case results");
  314. is($tap->{'global_status'},5, "Test global result is FAIL on todo pass test w/ bad plan");
  315. my $srs = $tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'};
  316. is($srs->[-1]->{'content'},"Bad Plan.","Bad plan noted in step results");
  317. }
  318. undef $opts->{'step_results'};
  319. #Check instant pizza
  320. $fcontents = "
  321. todo_pass.test ..
  322. 1..2
  323. ";
  324. undef $opts->{'source'};
  325. $opts->{'tap'} = $fcontents;
  326. $opts->{'step_results'} = 'step_results';
  327. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  328. is($res,undef,"TR Parser doesn't explode on instantiation");
  329. isa_ok($tap,"Test::Rail::Parser");
  330. if (!$res) {
  331. $tap->run();
  332. is($tap->{'errors'},0,"No errors encountered uploading case results");
  333. is($tap->{'global_status'},4, "Test global result is retest when insta-bombout occurs");
  334. my $srs = $tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'};
  335. is($srs->[-1]->{'content'},"Bad Plan.","Bad plan noted in step results");
  336. }
  337. undef $opts->{'step_results'};
  338. #Check unplanned tests
  339. $fcontents = "
  340. todo_pass.test ..
  341. 1..1
  342. ok 1 - STORAGE TANKS SEARED
  343. ok 2 - ZIPPPEEE
  344. ";
  345. $opts->{'tap'} = $fcontents;
  346. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  347. is($res,undef,"TR Parser doesn't explode on instantiation");
  348. isa_ok($tap,"Test::Rail::Parser");
  349. if (!$res) {
  350. $tap->run();
  351. is($tap->{'errors'},0,"No errors encountered uploading case results w/ unplanned tests");
  352. is($tap->{'global_status'},5, "Test global result is FAIL when unplanned test seen without case-per-ok");
  353. }
  354. undef $tap;
  355. #Check bad plan w/ todo pass logic
  356. $fcontents = "
  357. todo_pass.test ..
  358. 1..2
  359. ok 1 - STORAGE TANKS SEARED #TODO todo pass
  360. # goo
  361. % mark_status=todo_fail #Appears tanks weren't so sealed after all
  362. ";
  363. undef $opts->{'source'};
  364. $opts->{'tap'} = $fcontents;
  365. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  366. is($res,undef,"TR Parser doesn't explode on instantiation");
  367. isa_ok($tap,"Test::Rail::Parser");
  368. if (!$res) {
  369. $tap->run();
  370. is($tap->{'errors'},0,"No errors encountered uploading case results");
  371. is($tap->{'global_status'},7, "Test global result is respected when using global status override");
  372. }
  373. undef $opts->{'tap'};
  374. #Check autoclose functionality against Run with all tests in run status.
  375. undef $tap;
  376. $opts->{'source'} = 't/skip.test';
  377. $opts->{'run'} = 'FinalRun';
  378. $opts->{'autoclose'} = 1;
  379. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  380. is($res,undef,"TR Parser doesn't explode on instantiation");
  381. isa_ok($tap,"Test::Rail::Parser");
  382. if (!$res) {
  383. $tap->run();
  384. is($tap->{'errors'},0,"No errors encountered uploading case results");
  385. is($tap->{'run_closed'},1, "Run closed by parser when all tests done");
  386. }
  387. #Check autoclose functionality against Run with not all tests in run status.
  388. undef $tap;
  389. $opts->{'source'} = 't/todo_pass.test';
  390. $opts->{'run'} = 'BogoRun';
  391. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  392. is($res,undef,"TR Parser doesn't explode on instantiation");
  393. isa_ok($tap,"Test::Rail::Parser");
  394. if (!$res) {
  395. $tap->run();
  396. is($tap->{'errors'},0,"No errors encountered uploading case results");
  397. is($tap->{'run_closed'},undef, "Run not closed by parser when results are outstanding");
  398. }
  399. #Check that autoclose works against plan with all tests in run status
  400. undef $tap;
  401. $opts->{'source'} = 't/fake.test';
  402. $opts->{'run'} = 'FinalRun';
  403. $opts->{'plan'} = 'FinalPlan';
  404. $opts->{'configs'} = ['testConfig'];
  405. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  406. is($res,undef,"TR Parser doesn't explode on instantiation");
  407. isa_ok($tap,"Test::Rail::Parser");
  408. if (!$res) {
  409. $tap->run();
  410. is($tap->{'errors'},0,"No errors encountered uploading case results");
  411. is($tap->{'plan_closed'},1, "Plan closed by parser when all tests done");
  412. }
  413. #Check that autoclose works against plan with all tests not in run status
  414. undef $tap;
  415. $opts->{'run'} = 'BogoRun';
  416. $opts->{'plan'} = 'BogoPlan';
  417. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  418. is($res,undef,"TR Parser doesn't explode on instantiation");
  419. isa_ok($tap,"Test::Rail::Parser");
  420. if (!$res) {
  421. $tap->run();
  422. is($tap->{'errors'},0,"No errors encountered uploading case results");
  423. is($tap->{'plan_closed'},undef, "Plan not closed by parser when results are outstanding");
  424. }
  425. #Plan but no run 'splodes
  426. undef $tap;
  427. $opts->{'plan'} = 'CompletePlan';
  428. delete $opts->{'run'};
  429. delete $opts->{'configs'};
  430. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  431. like($res,qr/but no run passed/i,"TR Parser explodes on instantiation due to passing plan with no run");
  432. #Check that trying without spawn opts, using completed plan fails
  433. undef $tap;
  434. $opts->{'plan'} = 'ClosedPlan';
  435. $opts->{'run'} = 'BogoRun';
  436. delete $opts->{'testsuite_id'};
  437. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  438. like($res,qr/plan provided is completed/i,"TR Parser explodes on instantiation due to passing closed plan");
  439. #Check that the above two will just spawn a new plan in these cases
  440. $opts->{'testsuite_id'} = 9;
  441. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  442. is($res,undef,"TR Parser runs all the way through on completed run when spawning");
  443. #Check that trying without spawn opts, using completed run fails
  444. undef $tap;
  445. delete $opts->{'testsuite_id'};
  446. delete $opts->{'plan'};
  447. $opts->{'run'} = 'ClosedRun';
  448. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  449. like($res,qr/run provided is completed/i,"TR Parser explodes on instantiation due to passing closed run");
  450. #Check that the above two will just spawn a new run in these cases
  451. $opts->{'testsuite_id'} = 9;
  452. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  453. is($res,undef,"TR Parser runs all the way through on completed run when spawning");
  454. $fcontents = "
  455. todo_pass.test ..
  456. 1..2
  457. ok 1 - STORAGE TANKS SEARED #TODO todo pass
  458. # goo
  459. Bail out! #YOLO
  460. ";
  461. undef $opts->{'source'};
  462. $opts->{'tap'} = $fcontents;
  463. $opts->{'step_results'} = 'step_results';
  464. $res = exception { $tap = Test::Rail::Parser->new($opts) };
  465. is($res,undef,"TR Parser runs all the way through on bailout");
  466. if (!$res) {
  467. $tap->run();
  468. is($tap->{'errors'},0,"No errors encountered uploading case results");
  469. is($tap->{'global_status'},5, "Test global result is FAIL on todo pass test w/ bailout");
  470. my $srs = $tap->{'tr_opts'}->{'result_custom_options'}->{'step_results'};
  471. is($srs->[-1]->{'content'},"Bail Out!.","Bailout noted in step results");
  472. }