Module: Spectator::Specs

Included in:
ERunner
Defined in:
lib/spectator/emacs.rb

Instance Method Summary collapse

Instance Method Details

#check_if_bundle_neededObject

Checks if the commands bundle exec rspec and rspec actually run the same program, and sets the @bundle instance variable accordingly.

This is meant to speed up the execution of rspec.



233
234
235
236
237
238
239
# File 'lib/spectator/emacs.rb', line 233

def check_if_bundle_needed
  if `bundle exec #{rspec_command} -v` == `#{rspec_command} -v`
    @bundle = ""
  else
    @bundle = "bundle exec "
  end
end

#extract_rspec_stats(output) ⇒ Hash

Returns a hash that summarizes the rspec results.

Parameters:

  • output (String)

    the rspec output

Returns:

  • (Hash)

    a hash table with keys :examples, :failures, :pending, :summary, :status.

    • :examples => number of examples ran
    • :failures => number of failed examples
    • :pending => number of pending examples ran
    • :summary => the summary string from which the above have been extracted
    • :status => one of :failure, :pending, :success

Raises:



168
169
170
171
172
173
174
175
176
# File 'lib/spectator/emacs.rb', line 168

def extract_rspec_stats(output)
  summary_regex = /^(\d*)\sexamples?,\s(\d*)\s(errors?|failures?)[^\d]*((\d*)\spending)?/
  summary_line = output.split("\n").detect { |line| line.match(summary_regex) }
  matchdata = summary_line.match(summary_regex)
  raise SummaryExtractionError.new  if matchdata.nil?
  _, examples, failures, _, pending = matchdata.to_a
  stats = {:examples => examples.to_i, :failures => failures.to_i, :pending => pending.to_i, :summary => summary_line}
  stats.merge(:status =>  rspec_status(stats))
end

#extract_rspec_summary(output) ⇒ Hash

Returns a hash that summarizes the rspec results.

Redefine this method if you are using a non standard rspec formatter, see the README for details.

Parameters:

  • output (String)

    the rspec output

Returns:

  • (Hash)

    a hash table with keys :examples, :failures, :pending, :summary, :status.

    • :examples: number of examples ran
    • :failures: number of failed examples
    • :pending: number of pending examples ran
    • :summary: the summary string from which the above have been extracted
    • :status: one of

       :success, :pending, :failure
      


194
195
196
# File 'lib/spectator/emacs.rb', line 194

def extract_rspec_summary(output)
  extract_rspec_stats output
end

#rspec(options) ⇒ Object

Runs the rspec command with the given options, and notifies Emacs of the results.

Parameters:

  • options (String)

    The command line arguments to pass to rspec.



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/spectator/emacs.rb', line 269

def rspec(options)
  unless options.empty?
    results = run("#{@bundle}#{rspec_command} --failure-exit-code 99 #{options}")
    status = results[:status].exitstatus
    if status == 1
      puts "An error occurred when running the tests".red
      puts "RSpec output:"
      puts "STDERR:"
      puts results[:stderr]
      puts "-" * 80
      puts "STDOUT:"
      puts results[:stdout]
      puts "sending error message"
      send_error(results[:stdout], results[:stderr])
    else
      begin
        stats = extract_rspec_summary results[:stdout]
        puts(stats[:summary].send(results[:status] == 0 ? :green : :red))
        # enotify_notify results[:stdout], stats
        rspec_send_results results[:stdout], stats
      rescue StandardError => e
        puts "ERROR extracting summary from rspec output: #{e}".red
        puts e.backtrace
        puts "RSpec output:"
        puts "STDERR:"
        puts results[:stderr]
        puts "-" * 80
        puts "STDOUT:"
        puts results[:stdout]
        print "Exit? (y/N)"
        answer = STDIN.gets
        abort "Execution aborted by the user"  if answer.strip.downcase == 'y'
      end
    end
  end
end

#rspec_send_results(rspec_output, stats) ⇒ Object

Sends a notification to emacs via Enotify

Parameters:

  • rspec_output (String)

    The rspec command output

  • stats (Hash)

    A Hash table with keys :examples, :failures, :pending, :summary, :status. See #extract_rspec_summary for details about the meaning of the key/value pairs in this table.



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/spectator/emacs.rb', line 215

def rspec_send_results(rspec_output, stats)
  begin
    print "--- Sending notification to #{@enotify_host}:#{@enotify_port}" \
    " through #{@enotify_slot_id}... ".cyan
    enotify_notify rspec_output, stats
    puts "Success!".green
  rescue SocketError
    puts "Failed!".red
    enotify_connect
    rspec_send_results rspec_output, stats
  end
end

#rspec_status(rspec_stats) ⇒ Object

Summarizes the rspec results as one of :failure, :pending, :success.

Parameters:

  • rspec_stats (Hash)

    A Hash table with keys :examples, :failures, :pending, :summary, :status. See #extract_rspec_summary for details about the meaning of the key/value pairs in this table.



148
149
150
151
152
153
154
155
156
# File 'lib/spectator/emacs.rb', line 148

def rspec_status(rspec_stats)
  if rspec_stats[:failures] > 0
    :failure
  elsif rspec_stats[:pending] > 0
    :pending
  else
    :success
  end
end

#run(cmd) ⇒ Hash

Runs a command and returns a hash containing exit status, standard output and standard error contents.

Returns:

  • (Hash)

    a hash table with keys :status, :stdout, :stderr.



202
203
204
205
206
207
208
# File 'lib/spectator/emacs.rb', line 202

def run(cmd)
  puts "=== running: #{cmd} ".ljust(terminal_columns, '=').cyan
  pid, _, stdout, stderr = Open4::popen4 cmd
  _, status = Process::waitpid2 pid
  puts "===".ljust(terminal_columns, '=').cyan
  {:status => status, :stdout => stdout.read.strip, :stderr => stderr.read.strip}
end

#send_error(stdout, stderr) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/spectator/emacs.rb', line 241

def send_error(stdout, stderr)
  report_header = """################################## ERROR REPORT ##################################

An error happened during the test run. Check your spec files.

>-------------------------------- Error Message --------------------------------<
"""



  message = {
    :id => @enotify_slot_id,
    :notification => {
      :text => @notification_messages[:error],
      :face => @notification_face[:error],
      :help => "", # format_tooltip(stats),
      :mouse_1 => "tdd"
    },
    :data => { :mode => "org", :report_text => report_header + stdout + stderr }
  }

  enotify_send message
end