diff --git a/example/spec/example_spec.rb b/example/spec/example_spec.rb index da25204..5157a34 100644 --- a/example/spec/example_spec.rb +++ b/example/spec/example_spec.rb @@ -48,4 +48,9 @@ $stdout.puts "Test" $stderr.puts "Bar" end + + it "should support multiple failures", aggregate_failures: true do + expect('foo').to eq 1 + expect('bar').to eq 2 + end end diff --git a/lib/rspec_junit_formatter/rspec3.rb b/lib/rspec_junit_formatter/rspec3.rb index af59096..218e0f2 100644 --- a/lib/rspec_junit_formatter/rspec3.rb +++ b/lib/rspec_junit_formatter/rspec3.rb @@ -88,7 +88,13 @@ def failure_message_for(example) end def failure_for(notification) - strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n") + exception = exception_for(notification) + + if aggregate_failure?(exception) + strip_diff_colors(exception.message) + else + strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n") + end end def exception_for(notification) @@ -141,6 +147,13 @@ def stdout_for(example_notification) def stderr_for(example_notification) example_notification.example.metadata[:stderr] end + + def aggregate_failure?(exception) + # Introduced in rspec 3.3 + return false unless defined?(RSpec::Expectations::MultipleExpectationsNotMetError) + + exception.is_a?(RSpec::Expectations::MultipleExpectationsNotMetError) + end end # rspec-core 3.0.x forgot to mark this as a module function which causes: diff --git a/spec/rspec_junit_formatter_spec.rb b/spec/rspec_junit_formatter_spec.rb index 7a9d1dc..0f5bc49 100644 --- a/spec/rspec_junit_formatter_spec.rb +++ b/spec/rspec_junit_formatter_spec.rb @@ -52,6 +52,7 @@ def execute_example_spec let(:failed_testcases) { doc.xpath("/testsuite/testcase[failure]") } let(:shared_testcases) { doc.xpath("/testsuite/testcase[contains(@name, 'shared example')]") } let(:failed_shared_testcases) { doc.xpath("/testsuite/testcase[contains(@name, 'shared example')][failure]") } + let(:failed_multiple_testcases) { doc.xpath("/testsuite/testcase[contains(@name, 'multiple')][failure]") } # Combined into a single example so we don't have to re-run the example rspec # process over and over. (We need to change the parameters in later specs so @@ -63,9 +64,9 @@ def execute_example_spec expect(testsuite).not_to be(nil) expect(testsuite["name"]).to eql("rspec") - expect(testsuite["tests"]).to eql("12") + expect(testsuite["tests"]).to eql("13") expect(testsuite["skipped"]).to eql("1") - expect(testsuite["failures"]).to eql("8") + expect(testsuite["failures"]).to eql("9") expect(testsuite["errors"]).to eql("0") expect(Time.parse(testsuite["timestamp"])).to be_within(60).of(Time.now) expect(testsuite["time"].to_f).to be > 0 @@ -73,7 +74,7 @@ def execute_example_spec # it has some test cases - expect(testcases.size).to eql(12) + expect(testcases.size).to eql(13) testcases.each do |testcase| expect(testcase["classname"]).to eql("spec.example_spec") @@ -107,7 +108,7 @@ def execute_example_spec # it has failed test cases - expect(failed_testcases.size).to eql(8) + expect(failed_testcases.size).to eql(9) failed_testcases.each do |testcase| expect(testcase).not_to be(nil) @@ -134,6 +135,17 @@ def execute_example_spec expect(testcase.text).to include("shared_examples.rb") end + # it has detail for an aggregate_failures example + expect(failed_multiple_testcases.size).to eql(1) + failed_multiple_testcases.each do |testcase| + expect(testcase.text).to include("foo") + if Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new('3.3') + expect(testcase.text).to include("bar") + else + expect(testcase.text).to_not include("bar") + end + end + # it cleans up diffs diff_testcase_failure = doc.xpath("//testcase[contains(@name, 'diffs')]/failure").first