Class: Kensho::RSpec::Formatter
- Inherits:
-
RSpec::Core::Formatters::BaseFormatter
- Object
- RSpec::Core::Formatters::BaseFormatter
- Kensho::RSpec::Formatter
- Defined in:
- lib/kensho/rspec/formatter.rb
Constant Summary collapse
- SEVERITY_KEYS =
Kensho::Schema::SEVERITY.map(&:to_sym).freeze
- META_BLOCKLIST =
Metadata keys that aren’t user tags. We prune these from the tag list so RSpec’s housekeeping (location, type, file_path, etc.) doesn’t pollute case.tags.
%i[ absolute_file_path block default_path described_class description described_class_name described_class_name described_at description_args execution_result file_path file_path_proc full_description kensho_feature kensho_epic kensho_story last_run_status line_number location parent_example_group rerun_file_path scoped_id severity shared_group_inclusions shared_group_metadata shared_group_inclusion_backtrace skip stack_frames type variants ].to_set
Instance Method Summary collapse
- #example_failed(notification) ⇒ Object
- #example_group_started(notification) ⇒ Object
- #example_passed(notification) ⇒ Object
- #example_pending(notification) ⇒ Object
- #example_started(notification) ⇒ Object
-
#initialize(output = nil) ⇒ Formatter
constructor
A new instance of Formatter.
-
#install_capture_hook! ⇒ Object
Tee stdout/stderr around each example into the per-case scratch so case.logs[] picks up ‘puts` calls without the user having to do anything.
-
#register_attachment(scratch, src_path, kind:, name:, mime_type:) ⇒ Object
—– internals —– #.
-
#start(_notification) ⇒ Object
—– lifecycle hooks —– #.
- #stop(_notification) ⇒ Object
Constructor Details
#initialize(output = nil) ⇒ Formatter
Returns a new instance of Formatter.
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 |
# File 'lib/kensho/rspec/formatter.rb', line 65 def initialize(output = nil) # RSpec's BaseFormatter wants an output IO; we never write to it, # but we still hand one up so RSpec doesn't blow up. super(output || StringIO.new) @output_dir = File.(ENV['KENSHO_OUTPUT'] || (defined?(Kensho::RSpec::DEFAULT_OUTPUT) ? Kensho::RSpec::DEFAULT_OUTPUT : 'kensho-results')) @cases_dir = File.join(@output_dir, 'cases') @attachments_dir = File.join(@output_dir, 'attachments') @project = { 'name' => ENV['KENSHO_PROJECT_NAME'] || 'Unknown project', 'slug' => ENV['KENSHO_PROJECT_SLUG'] || Kensho::Schema.slugify(ENV['KENSHO_PROJECT_NAME'] || 'unknown') } @run_id = ENV['KENSHO_RUN_ID'] || Kensho::Schema.default_run_id @severity_from_meta = ENV['KENSHO_NO_SEVERITY_FROM_META'].to_s.empty? @started_at = Kensho::Schema.iso_now @started_perf = monotonic_now @rootpath = Dir.pwd @cases_by_id = {} @ids_seen = Hash.new(0) @groups = {} FileUtils.mkdir_p(@cases_dir) FileUtils.mkdir_p(@attachments_dir) Kensho::RSpec::State.formatter = self install_capture_hook! end |
Instance Method Details
#example_failed(notification) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/kensho/rspec/formatter.rb', line 161 def example_failed(notification) ex = notification.example.execution_result.exception status = if ex && (ex.class.name == 'RSpec::Expectations::ExpectationNotMetError') 'fail' elsif ex 'broken' else 'fail' end finalize(notification.example, status, ex) end |
#example_group_started(notification) ⇒ Object
136 137 138 139 |
# File 'lib/kensho/rspec/formatter.rb', line 136 def example_group_started(notification) group = notification.group @groups[group.[:scoped_id] || group.object_id] = (group) end |
#example_passed(notification) ⇒ Object
157 158 159 |
# File 'lib/kensho/rspec/formatter.rb', line 157 def example_passed(notification) finalize(notification.example, 'pass', nil) end |
#example_pending(notification) ⇒ Object
174 175 176 |
# File 'lib/kensho/rspec/formatter.rb', line 174 def example_pending(notification) finalize(notification.example, 'skip', nil) end |
#example_started(notification) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/kensho/rspec/formatter.rb', line 141 def example_started(notification) example = notification.example case_obj = build_case(example) scratch = CaseScratch.new( case_id: case_obj['id'], example_id: example.id, started_at_ms: (Time.now.to_f * 1000.0) ) scratch.instance_variable_set(:@case_obj, case_obj) scratch.instance_variable_set(:@stdout_capture, StringIO.new) scratch.instance_variable_set(:@stderr_capture, StringIO.new) State.current = scratch @cases_by_id[case_obj['id']] = case_obj end |
#install_capture_hook! ⇒ Object
Tee stdout/stderr around each example into the per-case scratch so case.logs[] picks up ‘puts` calls without the user having to do anything. RSpec doesn’t expose a “captured output” API for arbitrary formatters, so we install a global before/after hook.
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 123 124 125 126 127 128 129 130 |
# File 'lib/kensho/rspec/formatter.rb', line 97 def install_capture_hook! return if @capture_installed @capture_installed = true ::RSpec.configure do |config| config.before(:each) do scratch = Kensho::RSpec::State.current next unless scratch stdout_io = StringIO.new stderr_io = StringIO.new scratch.instance_variable_set(:@orig_stdout, $stdout) scratch.instance_variable_set(:@orig_stderr, $stderr) scratch.instance_variable_set(:@stdout_io, stdout_io) scratch.instance_variable_set(:@stderr_io, stderr_io) $stdout = stdout_io $stderr = stderr_io end config.after(:each) do scratch = Kensho::RSpec::State.current next unless scratch stdout_io = scratch.instance_variable_get(:@stdout_io) stderr_io = scratch.instance_variable_get(:@stderr_io) orig_out = scratch.instance_variable_get(:@orig_stdout) orig_err = scratch.instance_variable_get(:@orig_stderr) $stdout = orig_out if orig_out $stderr = orig_err if orig_err scratch.instance_variable_set(:@stdout_text, stdout_io.string) if stdout_io scratch.instance_variable_set(:@stderr_text, stderr_io.string) if stderr_io end end end |
#register_attachment(scratch, src_path, kind:, name:, mime_type:) ⇒ Object
—– internals —– #
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/kensho/rspec/formatter.rb', line 186 def (scratch, src_path, kind:, name:, mime_type:) return nil unless File.file?(src_path) = File.join(@attachments_dir, scratch.case_id) FileUtils.mkdir_p() att_id = "att_#{SecureRandom.hex(4)}" dest_name = name || File.basename(src_path) dest = File.join(, "#{att_id}_#{dest_name}") begin FileUtils.cp(src_path, dest) rescue StandardError => e warn "[kensho] failed to copy #{src_path}: #{e.}" return nil end guessed_kind, guessed_mime = Kensho::Schema.kind_and_mime_for(src_path) rel = relpath(dest, @output_dir) record = { 'id' => att_id, 'kind' => kind || guessed_kind, 'relativePath' => rel, 'mimeType' => mime_type || guessed_mime } begin record['sizeBytes'] = File.size(dest) rescue StandardError # best-effort end record end |
#start(_notification) ⇒ Object
—– lifecycle hooks —– #
134 |
# File 'lib/kensho/rspec/formatter.rb', line 134 def start(_notification); end |