Skip to content

Commit

Permalink
Proof of concept coverage implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
A. Speller committed Sep 14, 2012
1 parent 296d1eb commit e4c15bc
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 5 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ gem 'yard'
gem 'redcarpet'
gem 'pry'
gem 'yajl-ruby'
gem 'tilt'
2 changes: 2 additions & 0 deletions lib/guard/jasmine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
require 'guard/guard'
require 'guard/watcher'

require 'guard/jasmine/jscoverage'

module Guard

# The Jasmine guard that gets notifications about the following
Expand Down
28 changes: 28 additions & 0 deletions lib/guard/jasmine/jscoverage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# coding: utf-8
require 'tilt'
class JasmineCoverage < Tilt::Template
def prepare
end

def evaluate(context, locals)
return data unless file.include?(Rails.root.to_s)
return data unless file.include?(Rails.root.join('app', 'assets').to_s)
filename = File.basename(file, '.coffee')
puts "Generating jscoverage instrumented file for #{file.gsub(Rails.root.to_s, '')}"
Dir.mktmpdir do |path|
Dir.mkdir File.join(path, 'in')
File.write File.join(path, 'in', filename), data
`jscoverage --encoding=UTF-8 #{path}/in #{path}/out`
raise "Could not genrate jscoverage instrumented file for #{file}" unless $?.success?
File.read File.join(path, 'out', filename)
end
end
end

if ENV['JSCOVERAGE'] == 'true' and defined?(Rails)
class GuardJasmineCoverageEngine < Rails::Engine
config.after_initialize do |app|
app.assets.register_postprocessor 'application/javascript', JasmineCoverage
end
end
end
29 changes: 25 additions & 4 deletions lib/guard/jasmine/phantomjs/lib/reporter.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions lib/guard/jasmine/phantomjs/src/reporter.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ class ConsoleReporter
failures: runner.results().failedCount
time: runtime
}

# Report jscoverage results if jscoverage data present
if window._$jscoverage?
@runnerResult['coverage'] = {}
totalLoc = 0
totalExecutedLoc = 0

for own file of window._$jscoverage
lines = window._$jscoverage[file]
fileLoc = lines.filter((line) -> line?).length
totalLoc += fileLoc
executedLoc = lines.filter((line) -> line? and line > 0).length
totalExecutedLoc += executedLoc
# Report one line for each file
@runnerResult['coverage'][file] = (executedLoc / fileLoc) * 100

# Report total coverage
@runnerResult['coverage']['total'] = (totalExecutedLoc / totalLoc) * 100

# Delay the end runner message, so that logs and errors can be retreived in between
end = -> console.log "RUNNER_END"
Expand Down
42 changes: 41 additions & 1 deletion lib/guard/jasmine/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,15 @@ def evaluate_response(output, file, options)
result['file'] = file
notify_spec_result(result, options)
end


if result['coverage']
notify_coverage_result(result['coverage'], options)

if result['coverage']['total'] < 100
result['error'] = "Coverage below 100%"
end
end

result

rescue => e
Expand Down Expand Up @@ -230,6 +238,38 @@ def notify_spec_result(result, options)

Formatter.info("Done.\n")
end


# Notification about the coverage of a spec run, success or failure,
# and some stats.
#
# @param [Hash] coverage the coverage hash from the JSON
# @param [Hash] options the options for the execution
# @option options [Boolean] :notification show notifications
# @option options [Boolean] :hide_success hide success message notification
#
def notify_coverage_result(coverage, options)
percentage = '%.0f%' % coverage['total']
if coverage['total'] < 100.0
coverage.each_pair do |file, value|
next if file == 'total'
next unless value
coverage_for_file = "#{file}: #{'%.0f' % value}%"
if value < 100
Formatter.error(coverage_for_file)
else
Formatter.success(coverage_for_file)
end
end
Formatter.error("Code Coverage: #{percentage}")
Formatter.notify("#{percentage} covered", :title => "Code coverage below 100%", :image => :failed, :priority => 2) if options[:notification]
else
Formatter.success('Code Coverage: 100%')
Formatter.notify("#{percentage} covered", :title => 'Code Coverage') if options[:notification] && !options[:hide_success]
end
rescue Exception => e
puts e.backtrace
end

# Specdoc like formatting of the result.
#
Expand Down
129 changes: 129 additions & 0 deletions spec/guard/jasmine/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,64 @@
JSON
end

let(:phantomjs_partial_coverage_response) do
<<-JSON
{
"passed": true,
"stats": {
"specs": 1,
"failures": 0,
"time": 0.009
},
"coverage": {
"application.js": 50.12,
"todo.js": 100.0,
"total": 84.78260869565217
},
"suites": [
{
"description": "Success suite",
"specs": [
{
"description": "Success test tests something",
"passed": true
}
]
}
]
}
JSON
end

let(:phantomjs_full_coverage_response) do
<<-JSON
{
"passed": true,
"stats": {
"specs": 1,
"failures": 0,
"time": 0.009
},
"coverage": {
"application.js": 100.0,
"todo.js": 100.0,
"total": 100.0
},
"suites": [
{
"description": "Success suite",
"specs": [
{
"description": "Success test tests something",
"passed": true
}
]
}
]
}
JSON
end

let(:phantomjs_command) do
"/usr/local/bin/phantomjs #{ @project_path }/lib/guard/jasmine/phantomjs/guard-jasmine.coffee"
end
Expand Down Expand Up @@ -195,6 +253,11 @@
response.first.should be_false
response.last.should =~ []
end

it "does not show coverage" do
runner.should_not_receive(:notify_coverage_result)
runner.run(['spec/javascripts/a.js.coffee'], defaults)
end

context 'with notifications' do
it 'shows an error notification' do
Expand Down Expand Up @@ -234,6 +297,12 @@
response.last.should =~ ['spec/javascripts/x/b.js.coffee']
end


it "does not show coverage" do
runner.should_not_receive(:notify_coverage_result)
runner.run(['spec/javascripts/a.js.coffee'], defaults)
end

context 'with the specdoc set to :never' do
context 'and console and errors set to :never' do
it 'shows the summary in the console' do
Expand Down Expand Up @@ -572,7 +641,67 @@
response.first.should be_true
response.last.should =~ []
end

context "with coverage" do

context 'when coverage is present' do
before do
IO.stub(:popen).and_return StringIO.new(phantomjs_full_coverage_response)
end


it 'notifies coverage when present' do
runner.should_receive(:notify_coverage_result)
runner.run(['spec/javascripts/t.js.coffee'], defaults)
end

it 'shows a success notification' do
formatter.should_receive(:notify).with("1 spec, 0 failures\nin 0.009 seconds", :title=>"Jasmine suite passed")
formatter.should_receive(:notify).with('100% covered', :title => "Code Coverage")
runner.run(['spec/javascripts/t.js.coffee'], defaults)
end

it 'logs the coverage to the console' do
formatter.should_receive(:success).with('Code Coverage: 100%')
runner.run(['spec/javascripts/t.js.coffee'], defaults)
end


context 'when coverage is below 100%' do
before do
IO.stub(:popen).and_return StringIO.new(phantomjs_partial_coverage_response)
end

it 'shows a failure notification' do
formatter.should_receive(:notify).with(
"85% covered",
:title => 'Code coverage below 100%',
:image => :failed,
:priority => 2
)
runner.run(['spec/javascripts/t.js.coffee'], defaults)
end

it 'logs the coverage to the console for all the files' do
formatter.should_receive(:error).with('Code Coverage: 85%')
formatter.should_receive(:error).with('application.js: 50%')
formatter.should_receive(:success).with('todo.js: 100%')

runner.run(['spec/javascripts/t.js.coffee'], defaults)
end

it 'fails the build' do
response = runner.run(['spec/javascripts/x/b.js.coffee'], defaults)
response.first.should be_false
response.last.should =~ []
end


end
end

end

context 'with the specdoc set to :always' do
it 'shows the specdoc in the console' do
formatter.should_receive(:info).with(
Expand Down

0 comments on commit e4c15bc

Please sign in to comment.