class RSpecJUnitFormatter
Based on XML schema: windyroad.org/dl/Open%20Source/JUnit.xsd<br>Dumps rspec results as a JUnit XML file.
def classname_for(example)
def classname_for(example) fp = example_group_file_path_for(example) fp.sub(%r{\.[^/.]+\Z}, "").gsub("/", ".").gsub(/\A\.+|\.+\Z/, "") end
def classname_for(notification)
def classname_for(notification) fp = example_group_file_path_for(notification) fp.sub(%r{\.[^/]*\Z}, "").gsub("/", ".").gsub(%r{\A\.+|\.+\Z}, "") end
def description_for(example)
def description_for(example) example.full_description end
def description_for(notification)
def description_for(notification) notification.example.full_description end
def dump_summary(duration, example_count, failure_count, pending_count)
def dump_summary(duration, example_count, failure_count, pending_count) super xml_dump end
def dump_summary(notification)
def dump_summary(notification) @summary_notification = notification xml_dump end
def duration
def duration @summary_notification.duration end
def duration_for(example)
def duration_for(example) example.execution_result[:run_time] end
def duration_for(notification)
def duration_for(notification) notification.example.execution_result.run_time end
def escape(text)
def escape(text) # Make sure it's utf-8 (this will throw errors for bad output, but that # seems okay) and replace invalid xml characters with entities text.to_s.encode(Encoding::UTF_8).gsub(ESCAPE_REGEXP, ESCAPE_ENTITY) end
def example_count
def example_count @summary_notification.examples.count end
def example_group_file_path_for(example)
def example_group_file_path_for(example) meta = example.metadata while meta[:example_group] meta = meta[:example_group] end meta[:file_path] end
def example_group_file_path_for(notification)
def example_group_file_path_for(notification) metadata = notification.example.metadata[:example_group] while parent_metadata = metadata[:parent_example_group] metadata = parent_metadata end metadata[:file_path] end
def examples
def examples @examples_notification.notifications end
def exception_for(example)
def exception_for(example) example.execution_result[:exception] end
def exception_for(notification)
def exception_for(notification) notification.example.execution_result.exception end
def failure_count
def failure_count @summary_notification.failed_examples.count end
def failure_for(example)
def failure_for(example) exception = exception_for(example) backtrace = format_backtrace(exception.backtrace, example) if shared_group = find_shared_group(example) backtrace << "Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\" called from #{shared_group.metadata[:example_group][:location]}" end "#{exception.message}\n#{backtrace.join("\n")}" end
def failure_for(notification)
def failure_for(notification) notification.message_lines.join("\n") << "\n" << notification.formatted_backtrace.join("\n") end
def find_shared_group(example)
def find_shared_group(example) group_and_parent_groups(example).find { |group| group.metadata[:shared_group_name] } end
def group_and_parent_groups(example)
def group_and_parent_groups(example) example.example_group.parent_groups + [example.example_group] end
def result_of(example)
def result_of(example) example.execution_result[:status] end
def result_of(notification)
def result_of(notification) notification.example.execution_result.status end
def start(example_count)
def start(example_count) @started = Time.now super end
def start(notification)
def start(notification) @start_notification = notification @started = Time.now super end
def stop(notification)
def stop(notification) @examples_notification = notification end
def xml_dump
def xml_dump output << %{<?xml version="1.0" encoding="UTF-8"?>\n} output << %{<testsuite} output << %{ name="rspec#{escape(ENV["TEST_ENV_NUMBER"].to_s)}"} output << %{ tests="#{example_count}"} output << %{ failures="#{failure_count}"} output << %{ errors="0"} output << %{ time="#{escape("%.6f" % duration)}"} output << %{ timestamp="#{escape(started.iso8601)}"} output << %{>\n} output << %{<properties>\n} output << %{<property} output << %{ name="seed"} output << %{ value="#{escape(RSpec.configuration.seed.to_s)}"} output << %{/>\n} output << %{</properties>\n} xml_dump_examples output << %{</testsuite>\n} end
def xml_dump_example(example)
def xml_dump_example(example) output << %{<testcase} output << %{ classname="#{escape(classname_for(example))}"} output << %{ name="#{escape(description_for(example))}"} output << %{ file="#{escape(example_group_file_path_for(example))}"} output << %{ time="#{escape("%.6f" % duration_for(example))}"} output << %{>} yield if block_given? output << %{</testcase>\n} end
def xml_dump_examples
def xml_dump_examples examples.each do |example| send :"xml_dump_#{result_of(example)}", example end end
def xml_dump_failed(example)
def xml_dump_failed(example) exception = exception_for(example) xml_dump_example(example) do output << %{<failure} output << %{ message="#{escape(exception.to_s)}"} output << %{ type="#{escape(exception.class.name)}"} output << %{>} output << escape(failure_for(example)) output << %{</failure>} end end
def xml_dump_passed(example)
def xml_dump_passed(example) xml_dump_example(example) end
def xml_dump_pending(example)
def xml_dump_pending(example) xml_dump_example(example) do output << %{<skipped/>} end end