When developing TDD or BDD in Ruby (1.9.2)
using the RCov::VerifyTask
you need to fullfill a certain threshold
to make a build successful.
It can be quite annoying to update the (hopefully) increased threshold
of the
RCov::VerifyTask
in your Rakefile
after each successful build.
So I did some experiments and the following script is the result.
A common RCov::VerifyTask
setup might look like:
Spec::Rake::SpecTask.new('rcov') do |t|
t.spec_files = FileList['spec/**/*.rb']
t.rcov = true
t.rcov_opts = ['--exclude', 'lib', '--exclude', 'gems']
t.libs << Dir["lib/**/*"]
end
RCov::VerifyTask.new(:verify_rcov) do |t|
t.threshold = 10.00 # to get started
t.index_html = 'coverage/index.html' # the path to html report
end
It uses another :task
to capture the output of the actual RCov::VerifyTask
and writes the threshold
into a coverage.yml
file. This threshold
value
is taken into comparison at the next build and updated at next build if
its value
has increased.
First the method to read and write the threshold
value from/to
a ./coverage.yml
.
# the `log' file in `yaml' format
#
COVERAGE_YML = 'coverage.yml'
# read the last 'threshold' from the .yml file
# and return `10.0' as value if the file isn't existant
#
def read_yaml_threshold
threshold = 10.0
return threshold unless File.exist? COVERAGE_YML
yaml = read_yaml_file COVERAGE_YML
threshold = yaml["THRESHOLD"].to_s
threshold.to_f
end
# write the given `value' in `yaml' format
# back into `log' file.
#
def write_yaml_threshold value
File.open(COVERAGE_YML, 'w') do |f|
f.write({"THRESHOLD" => value}.to_yaml)
end
end
Now the updated rake tasks.
# read the previous threshold once and
# reuse it in tasks to reduce file-access
#
@old_threshold = read_yaml_threshold
# the SpecTask from above
#
desc "Run all rspec tests with RCOV"
Spec::Rake::SpecTask.new('rcov') do |t|
t.spec_files = FileList['spec/**/*.rb']
t.rcov = true
t.rcov_opts = ['--exclude', 'lib', '--exclude', 'gems']
t.libs << Dir["lib/**/*"]
end
# the "verify" task which is still executable
# because the`threshold' property contains the
# current `threhold' value from `coverage.yml'
#
desc "Check code-coverage of project"
RCov::VerifyTask.new(:verify_rcov) do |t|
threshold = @old_threshold
Rake::Task['rcov'].execute
t.threshold = threshold
t.index_html = 'coverage/index.html'
end
# the actual 'capture and update' task which retrieves the 'previous'
# threshold and executes the `VerifyTask' and captures the 'new' threshold
# and finally compares them. if `new' threshold has increased the
# `coverage.yml' is updated.
#
task :run_verify do |t|
old_threshold = @old_threshold
log = `rake verify_rcov -f #{__FILE__}` # | tee coverage_log.txt`
new_threshold = threshold_from log
if new_threshold.to_f > old_threshold.to_f
begin
write_yaml_threshold new_threshold
rescue => e
puts "ERROR #{e.message} "
end
puts "Finished ..."
else
if new_threshold.to_f >= old_threshold.to_f
puts "Finished with `coverage' of #{new_threshold}% ..."
else
puts "Failed to finish with `coverage' of #{old_threshold}% => #{new_threshold}% ..."
end
end
end
Although i’m quite happy with it as it works for me i would like to see if either there’s a more convenient or `nerdy’ way to implement this. I’m still learning and every input is highly appreciated. :)
If you found this useful feel free to share or comment.
Regards
~David