Skip to content

Instantly share code, notes, and snippets.

@juanger
Forked from dblock/failures_formatter.rb
Last active May 27, 2020 17:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juanger/6055797 to your computer and use it in GitHub Desktop.
Save juanger/6055797 to your computer and use it in GitHub Desktop.
Rerun rspec failed tests and merge junit reports for jenkins.
# inspired by https://github.com/rspec/rspec-core/pull/596
require 'rspec/core/formatters/base_formatter'
module RSpec
module Core
module Formatters
class FailuresFormatter < BaseFormatter
def dump_failures
return if failed_examples.empty?
f = File.new("rspec.failures", "w+")
failed_examples.each do |example|
f.puts retry_command(example)
end
f.close
end
def retry_command(example)
example_name = example.full_description.gsub("\"", "\\\"")
"-e \"#{example_name}\""
end
end
end
end
end
#
# Organize RSpec tests in suites w/ retry. Requires rspec-core 2.11.0.
#
# (c) 2012 Daniel Doubrovkine, Art.sy
# (c) 2013 Juan Castaneda
# MIT License
#
require 'rspec/core/rake_task'
SPEC_SUITES = [
{ :id => :initializers, :title => 'initializers', :pattern => "spec/initializers/**/*_spec.rb" },
{ :id => :models, :title => 'model tests', :pattern => "spec/models/**/*_spec.rb" },
{ :id => :acceptance, :title => 'acceptance tests', :pattern => "spec/acceptance/**/*_spec.rb" },
{ :id => :controllers, :title => 'controller tests', :pattern => "spec/controllers/**/*_spec.rb" },
{ :id => :views, :title => 'view tests', :pattern => "spec/views/**/*_spec.rb" },
{ :id => :mailers, :title => 'mailer tests', :pattern => "spec/mailers/*_spec.rb" },
]
namespace :spec do
namespace :suite do
SPEC_SUITES.each do |suite|
desc "Run all specs in #{suite[:title]} spec suite"
task "#{suite[:id]}" do
rspec_failures = File.join(Rails.root, 'rspec.failures')
FileUtils.rm_f rspec_failures
junit_retry = File.join(Rails.root, 'coverage/junit/retry.xml')
FileUtils.rm_f junit_retry
Rake::Task["spec:suite:#{suite[:id]}:run"].execute
unless $?.success?
puts "[#{Time.now}] Failed, retrying #{File.read(rspec_failures).split(/\n+/).count} failure(s) in spec:suite:#{suite[:id]} ..."
Rake::Task["spec:suite:#{suite[:id]}:retry"].execute
end
Rake::Task["spec:suite:xml_merge"].execute
end
RSpec::Core::RakeTask.new("#{suite[:id]}:run") do |t|
t.pattern = suite[:pattern]
t.verbose = false
t.fail_on_error = false
t.spec_opts = [
"--require", "#{Rails.root}/spec/support/formatters/failures_formatter.rb",
"--require", "yarjuf",
"--format", "RSpec::Core::Formatters::FailuresFormatter",
"-f", "JUnit", "-o", "coverage/junit/first.xml",
File.read(File.join(Rails.root, ".rspec")).split(/\n+/).map { |l| l.shellsplit }
].flatten
end
RSpec::Core::RakeTask.new("#{suite[:id]}:retry") do |t|
t.pattern = suite[:pattern]
t.verbose = false
t.fail_on_error = false
t.spec_opts = [
"--require", "yarjuf",
"-f", "JUnit", "-o", "coverage/junit/retry.xml",
"-O", File.join(Rails.root, 'rspec.failures'),
File.read(File.join(Rails.root, '.rspec')).split(/\n+/).map { |l| l.shellsplit }
].flatten
end
end
desc "Run all spec suites"
task :all => :environment do
failed_suites = []
SPEC_SUITES..each do |suite|
puts "Running spec:suite:#{suite[:id]} ..."
Rake::Task["spec:suite:#{suite[:id]}"].execute
failed_suites << suite unless $?.success?
end
raise "Spec suite failed" unless failed_suites.empty?
end
desc "Merge junit reports"
task :xml_merge do
results = Nokogiri::XML::Document.parse(File.open("coverage/junit/first.xml"))
if File.exists?("coverage/junit/retry.xml")
retries = Nokogiri::XML::Document.parse(File.open("coverage/junit/retry.xml"))
retries.xpath("testsuites/testsuite/testcase").each do |node|
original = results.xpath("testsuites/testsuite/testcase[@name='#{node.attribute('name')}']").first
original.replace(node)
end
end
File.open("coverage/junit/results.xml", 'w') {|f| f.write(results) }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment