diff --git a/lib/Test2/Harness/Renderer/JUnit.pm b/lib/Test2/Harness/Renderer/JUnit.pm index 7c3db7e..e47b2c3 100644 --- a/lib/Test2/Harness/Renderer/JUnit.pm +++ b/lib/Test2/Harness/Renderer/JUnit.pm @@ -176,9 +176,10 @@ sub render_event { # Ignore subtests return if ( $f->{'hubs'} && $f->{'hubs'}->[0]->{'nested'} ); - my $test_num = sprintf( "%04d", $event->{'assert_count'} || $f->{'assert'}->{'number'} || die Dumper $event); + my $test_num = $event->{'assert_count'} || $f->{'assert'}->{'number'}; + $test_num = sprintf "%04d", $test_num if defined $test_num; my $test_name = _squeaky_clean( $f->{'assert'}->{'details'} // 'UNKNOWN_TEST?' ); - my $test_string = defined $test_name ? "$test_num - $test_name" : $test_num; + $test_name = join " - ", grep { defined } $test_num, $test_name; $test->{'testsuite'}->{'tests'}++; $self->close_open_failure_testcase( $test, $test_num ); @@ -190,10 +191,10 @@ sub render_event { if ( $f->{'amnesty'} && grep { ( $_->{'tag'} // '' ) eq 'TODO' } @{ $f->{'amnesty'} } ) { # All TODO Tests if ( !$f->{'assert'}->{'pass'} ) { # Failing TODO - push @{ $test->{'testcase'} }, $self->xml->testcase( { 'name' => "$test_string (TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, "" ); + push @{ $test->{'testcase'} }, $self->xml->testcase( { 'name' => "$test_name (TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, "" ); } elsif ( $self->{'allow_passing_todos'} ) { # junit parsers don't like passing TODO tests. Let's just not tell them about it if $ENV{ALLOW_PASSING_TODOS} is set. - push @{ $test->{'testcase'} }, $self->xml->testcase( { 'name' => "$test_string (PASSING TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, "" ); + push @{ $test->{'testcase'} }, $self->xml->testcase( { 'name' => "$test_name (PASSING TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, "" ); } else { # Passing TODO (Failure) when not allowed. @@ -204,10 +205,10 @@ sub render_event { my ($todo_message) = map { $_->{'details'} } grep { $_->{'tag'} // '' eq 'TODO' } @{ $f->{'amnesty'} }; push @{ $test->{'testcase'} }, $self->xml->testcase( - { 'name' => "$test_string (TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, + { 'name' => "$test_name (TODO)", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, $self->xml->error( { 'message' => $todo_message, 'type' => "TodoTestSucceeded" }, - $self->_cdata("ok $test_string") + $self->_cdata("ok $test_name") ) ); @@ -215,7 +216,7 @@ sub render_event { } elsif ( $f->{'assert'}->{'pass'} ) { # Passing test push @{ $test->{'testcase'} }, $self->xml->testcase( - { 'name' => "$test_string", 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, + { 'name' => $test_name, 'time' => $run_time, 'classname' => $test->{'testsuite'}->{'name'} }, "" ); } @@ -223,12 +224,15 @@ sub render_event { $test->{'testsuite'}->{'failures'}++; $test->{'testsuite'}->{'errors'}++; + my $message = "not ok" . ( $test_name ? " $test_name" : "" ); + # Trap the test information. We can't generate the XML for this test until we get all the diag information. $test->{'last_failure'} = { - 'test_num' => $test_num, - 'test_name' => $test_name, - 'time' => $run_time, - 'message' => "not ok $test_string\n", + 'test_num' => $test_num, + 'test_name' => $test_name, + 'time' => $run_time, + 'message' => $message, + 'full_message' => "$message\n", }; } @@ -240,7 +244,7 @@ sub render_event { foreach my $line ( @{ $f->{'info'} } ) { next unless $line->{'details'}; chomp $line->{'details'}; - $test->{'last_failure'}->{'message'} .= "# $line->{details}\n"; + $test->{'last_failure'}->{'full_message'} .= "# $line->{details}\n"; } return; } @@ -293,17 +297,20 @@ sub close_open_failure_testcase { # This causes the entire suite to choke. We don't want this. # If we're here already, we've already failed the test. let's just make sure the person reviewing # it knows the test count was messed up. - if ( $fail->{'test_num'} == $new_test_number ) { - $fail->{'message'} .= "# WARNING This test number has already been seen. Duplicate TEST # in output!\n"; + if ( defined $fail->{'test_num'} + && defined $new_test_number + && $fail->{'test_num'} == $new_test_number ) + { + $fail->{'message'} + .= "# WARNING This test number has already been seen. Duplicate TEST # in output!\n"; } my $xml = $self->xml; push @{ $test->{'testcase'} }, $xml->testcase( - { 'name' => "$fail->{test_num} - $fail->{test_name}", 'time' => $fail->{'time'}, 'classname' => $test->{'testsuite'}->{'name'} }, + { 'name' => $fail->{'test_name'}, 'time' => $fail->{'time'}, 'classname' => $test->{'testsuite'}->{'name'} }, $xml->failure( - { 'message' => "not ok $fail->{test_num} - $fail->{test_name}", 'type' => 'TestFailed' }, - $self->_cdata( $fail->{'message'} ) - ) + { 'message' => $fail->{message}, 'type' => 'TestFailed' }, + $self->_cdata( $fail->{'full_message'} ) ) ); delete $test->{'last_failure'}; diff --git a/t/test-no-numbers/pass-1.tx b/t/test-no-numbers/pass-1.tx new file mode 100644 index 0000000..adc923c --- /dev/null +++ b/t/test-no-numbers/pass-1.tx @@ -0,0 +1,14 @@ +use Test2::V0; + +sub pass_ok { + my $ctx = context(); + $ctx->hub->format->set_no_numbers(1); + + pass("pass"); + + $ctx->release; +} + +pass_ok(); + +done_testing; diff --git a/t/test.t b/t/test.t index b1de626..9d38388 100644 --- a/t/test.t +++ b/t/test.t @@ -211,6 +211,72 @@ my $env = { # env passed to yath }, 'junit output' or diag explain $junit; } +{ + note "all tests are ok without numbers"; + + my $sdir = $dir . '-no-numbers'; + + $env->{JUNIT_TEST_FILE} = "$tmpdir/no-numbers.xml"; + + yath( + command => 'test', + args => [ $sdir, '--ext=tx', @renderers, '-v' ], + exit => 0, + env => $env, + test => sub { + my $out = shift; + + like( + $out->{output}, + qr{\Q( PASSED )\E.*\Qt/test-no-numbers/pass-1.tx\E}, + "t/test-no-numbers/pass-1.tx" + ); + + like( $out->{output}, qr/Result: PASSED/, "Result: PASSED" ); + }, + ); + + # checking xml file + ok -e $env->{JUNIT_TEST_FILE}, 'junit file exists'; + + my $junit = XML::Simple::XMLin( $env->{JUNIT_TEST_FILE} ); + like $junit => hash { + field testsuite => hash { + field errors => 0; + field failures => 0; + field id => D(); + field name => 'test-no-numbers_pass-1_tx'; + + field 'system-err' => hash { end; }; + field 'system-out' => hash { end; }; + + field 'testcase' => hash { + field 'pass' => hash { + field classname => 'test-no-numbers_pass-1_tx'; + field time => D(); + end; + }; + field 'Tear down.' => hash { + field classname => 'test-no-numbers_pass-1_tx'; + field time => D(); + end; + }; + + end; + }; + + field tests => 1; + field time => D(); + field timestamp => D(); + + end; + }; + + end; + + }, 'junit output' or diag explain $junit; +} + { note "plan ok - one failure";