Skip to content

Instantly share code, notes, and snippets.

@tenderlove tenderlove/cov.rb
Created Feb 13, 2015

Embed
What would you like to do?
require 'coverage'
require 'json'
# This must be run with this patch applied:
# https://bugs.ruby-lang.org/issues/10816
Coverage.start
require 'minitest'
class Minitest::Runnable
LOG = File.open('run_log.txt', 'w')
Minitest.after_run { LOG.close }
class << self
alias :old_run_one_method :run_one_method
def run_one_method klass, method_name, reporter
before = Coverage.peek_result
old_run_one_method klass, method_name, reporter
after = Coverage.peek_result
LOG.puts JSON.dump [ klass.name, method_name.to_s, before, after ]
end
end
end
require 'rugged'
require 'set'
require 'json'
require 'shellwords'
repo = Rugged::Repository.new '.'
lines_to_run = Set.new
repo.index.diff.each_patch { |patch|
delta = patch.delta
file = delta.old_file[:path]
patch.each_hunk { |hunk|
hunk.each_line { |line|
if line.line_origin == :addition
line = if line.new_lineno == -1
line.old_lineno
else
line.new_lineno
end
lines_to_run << [file, line]
end
}
}
}
def diff before, after
r = after.each_with_object({}) do |(k,v), res|
cov = v.zip(before[k]).map do |line_after, line_before|
if line_after
line_after - line_before
else
line_after
end
end
res[k] = cov
end
r.delete_if { |_, v| v.all? { |line| line.nil? || line == 0 } }
r
end
cov_map = Hash.new { |h, file|
h[file] = Hash.new { |i, line|
i[line] = []
}
}
File.open('run_log.txt') do |f|
f.each_line do |line|
klass, method, before, after = JSON.parse line
delta = diff before, after
delta.each_pair do |file, lines|
file_map = cov_map[file]
lines.each_with_index do |val, i|
next unless val && val > 0
file_map[i + 1] << [klass, method]
end
end
end
end
res = lines_to_run.flat_map do |file, line|
cov_map[File.expand_path(file)][line].map do |klass, method|
"#{klass}##{method}"
end
end
puts Shellwords.escape("/#{res.join('|')}/")
@JonRowe

This comment has been minimized.

Copy link

commented Feb 13, 2015

require 'coverage'
require 'json'

module RSpecLogger
  LOG = File.open('run_log.txt', 'w')
  Coverage.start

  after(:suite) { LOG.close }

  around(:example) do |example|
    before = Coverage.peek_result
    example.call
    after = Coverage.peek_result
    LOG.puts JSON.dump [ example.full_description, before, after ]
  end
end

RSpec.configuration.include RSpecLogger
@JonRowe

This comment has been minimized.

Copy link

commented Feb 13, 2015

E.g. the code above would be in your config and then your specs would call the what_to_run stuff... Assuming what_to_run is the code under test?

@tenderlove

This comment has been minimized.

Copy link
Owner Author

commented Feb 13, 2015

hmmm... I get an error: undefined method 'after' for RSpecLogger:Module

I guess there is no after method available on that module yet (which makes sense). Where should I look for docs on how to do this?

@tenderlove

This comment has been minimized.

Copy link
Owner Author

commented Feb 13, 2015

Never mind, I figured it out. Thanks!!

require 'coverage'
require 'json'
require 'rspec'

LOG = File.open('run_log.txt', 'w')
Coverage.start

RSpec.configuration.after(:suite) { LOG.close }

RSpec.configuration.around(:example) do |example|
  before = Coverage.peek_result
  example.call
  after = Coverage.peek_result
  LOG.puts JSON.dump [ example.full_description, before, after ]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.