Class: RspecErrorSummary::Parser
- Inherits:
-
Object
- Object
- RspecErrorSummary::Parser
- Defined in:
- lib/rspec_error_summary.rb
Overview
!/usr/bin/env ruby
Class Method Summary collapse
Class Method Details
.parse_spec_report(options = {}) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/rspec_error_summary.rb', line 9 def self.parse_spec_report( = {}) config = RSpec.configuration formatter = RSpec::Core::Formatters::JsonFormatter.new(config.output_stream) # create reporter with json formatter reporter = RSpec::Core::Reporter.new(config) config.instance_variable_set(:@reporter, reporter) # internal hack # api may not be stable, works on Rspec version 3.1 loader = config.send(:formatter_loader) notifications = loader.send(:notifications_for, RSpec::Core::Formatters::JsonFormatter) reporter.register_listener(formatter, *notifications) path = [:path] || "./spec/" desired_failure_string = [:search] || "" be_verbose = [:verbose] || false puts "Running tests... This may take a few minutes..." RSpec::Core::Runner.run([path]) json = formatter.output_hash failed_tests = json[:examples].select { |test| test[:status] == "failed" && test[:exception][:message].include?(desired_failure_string) } = failed_tests.map do |test| # Consume the failed tests and provide a more simplified hash with just the required info # Strip out the line breaks and replace standard space indents with tabs msg = test[:exception][:message].gsub("\n", " ").gsub(" ", "\n\t\t ").strip test_split = msg.split("#<") if(test_split.count > 1 && test_split[0] != "" && ![:verbose]) # Indicate that there is more to the message to be seen using the verbose flag # or by running rspec manually on the affected files msg = test_split[0] + "..." end { message: msg, file_path: test[:file_path], line_number: test[:line_number] } end = .uniq { |test| test[:message] } = [] .map do |failed_test| matching_failures = .select { |test| test[:message] == failed_test[:message] } files = matching_failures.map{ |test| [test[:file_path],test[:line_number]]} files.sort! do |a,b| # Sort by file path first, then line number comp = (a[0] <=> b[0]) comp.zero? ? (a[1] <=> b[1]) : comp end << { message: failed_test[:message], count: matching_failures.count, files: files } end # Sort by number of occurrences in descending order .sort!{ |a,b| b[:count].to_i <=> a[:count].to_i } # Empty space between any normal RSpec output and our custom text puts "\n\n" puts "Failure message report:\n\n" puts "Total # of failures: #{ failed_tests.count.to_s.colorize(:red) }" puts "Total # of unique errors: #{ .count.to_s.colorize(:red) }\n\n" if .count == 0 puts ("Either no failures in the specified tests, or the desired error you entered could not be found in the results").colorize(:green) else .each do |failure| puts " " count_text = ("#{failure[:count]} #{ failure[:count] > 1 ? 'occurrences' : 'occurrence'}").colorize(:red) msg_text = ((be_verbose ? failure[:message] : failure[:message].truncate(140,separator: /\s/))).colorize(:brown) puts %Q~#{count_text} - #{msg_text}~ failure[:files].each do |file| file_text = (file[0]).colorize(:blue) line_text = ("#{file[1].to_s}").colorize(:green) puts "\t\t#{file_text}:#{line_text}" end end end puts "\n\n" end |