summaryrefslogtreecommitdiff
path: root/scripts/failed_tests.rb
blob: fb13df7bf62bab2bc439e6758aae98fe4ac70b5e (plain)
1
2
3
4
5
6
7
8
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'optparse'
require 'fileutils'
require 'uri'
require 'json'
require 'set'

class FailedTests
  def initialize(options)
    @filename = options.delete(:previous_tests_report_path)
    @output_directory = options.delete(:output_directory)
    @rspec_pg_regex = options.delete(:rspec_pg_regex)
    @rspec_ee_pg_regex = options.delete(:rspec_ee_pg_regex)
  end

  def output_failed_test_files
    create_output_dir

    failed_files_for_suite_collection.each do |suite_collection_name, suite_collection_files|
      failed_test_files = suite_collection_files.map { |filepath| filepath.delete_prefix('./') }.join(' ')

      output_file = File.join(output_directory, "#{suite_collection_name}_failed_files.txt")

      File.open(output_file, 'w') do |file|
        file.write(failed_test_files)
      end
    end
  end

  def failed_files_for_suite_collection
    suite_map.each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |(suite_collection_name, suite_collection_regex), hash|
      failed_suites.each do |suite|
        hash[suite_collection_name].merge(failed_files(suite)) if suite['name'] =~ suite_collection_regex
      end
    end
  end

  def suite_map
    @suite_map ||= {
      rspec: rspec_pg_regex,
      rspec_ee: rspec_ee_pg_regex,
      jest: /jest/
    }
  end

  private

  attr_reader :filename, :output_directory, :rspec_pg_regex, :rspec_ee_pg_regex

  def file_contents
    @file_contents ||= begin
      File.read(filename)
    rescue Errno::ENOENT
      '{}'
    end
  end

  def file_contents_as_json
    @file_contents_as_json ||= begin
      JSON.parse(file_contents)
    rescue JSON::ParserError
      {}
    end
  end

  def failed_suites
    return [] unless file_contents_as_json['suites']

    file_contents_as_json['suites'].select { |suite| suite['failed_count'] > 0 }
  end

  def failed_files(suite)
    return [] unless suite

    suite['test_cases'].each_with_object([]) do |failure_hash, failed_cases|
      failed_cases << failure_hash['file'] if failure_hash['status'] == 'failed'
    end
  end

  def create_output_dir
    return if File.directory?(output_directory)

    puts 'Creating output directory...'
    FileUtils.mkdir_p(output_directory)
  end
end

if $0 == __FILE__
  options = {
    previous_tests_report_path: 'test_results/previous/test_reports.json',
    output_directory: 'tmp/previous_failed_tests/',
    rspec_pg_regex: /rspec .+ pg12( .+)?/,
    rspec_ee_pg_regex: /rspec-ee .+ pg12( .+)?/
  }

  OptionParser.new do |opts|
    opts.on("-p", "--previous-tests-report-path PREVIOUS_TESTS_REPORT_PATH", String, "Path of the file listing previous test failures") do |value|
      options[:previous_tests_report_path] = value
    end

    opts.on("-o", "--output-directory OUTPUT_DIRECTORY", String, "Output directory for failed test files") do |value|
      options[:output_directory] = value
    end

    opts.on("--rspec-pg-regex RSPEC_PG_REGEX", Regexp, "Regex to use when finding matching RSpec jobs") do |value|
      options[:rspec_pg_regex] = value
    end

    opts.on("--rspec-ee-pg-regex RSPEC_EE_PG_REGEX", Regexp, "Regex to use when finding matching RSpec EE jobs") do |value|
      options[:rspec_ee_pg_regex] = value
    end

    opts.on("-h", "--help", "Prints this help") do
      puts opts
      exit
    end
  end.parse!

  FailedTests.new(options).output_failed_test_files
end