Skip to content

Commit

Permalink
Merge branch 'coverage'
Browse files Browse the repository at this point in the history
  • Loading branch information
netzpirat committed Jan 22, 2013
2 parents b7d421c + 0b16287 commit 18a1689
Show file tree
Hide file tree
Showing 16 changed files with 748 additions and 249 deletions.
17 changes: 15 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
language: ruby
bundler_args: --without development
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- ruby-head
- ree
- rbx
- jruby
- jruby-18mode
- jruby-19mode
- jruby-head
- rbx-18mode
- rbx-19mode
matrix:
allow_failures:
- rvm: ruby-head
- rvm: jruby-head
branches:
only:
- master
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Master

- Switch coverage from [jscoverage](http://siliconforks.com/jscoverage/) to [Istanbul](https://github.com/gotwarlost/istanbul).
- [#77](https://github.com/netzpirat/guard-jasmine/pull/77): Add coverage support. ([@alexspeller][])

## 1.11.1 - January 11, 2013

- [#99](https://github.com/netzpirat/guard-jasmine/pull/99): Allowed passing custom rackup config via CLI. ([@arr-ee][])
Expand Down Expand Up @@ -326,6 +331,7 @@
- Fix inspector glob to get also non-coffee specs.
- Finish the runner phantomjs bridge.

[@alexspeller]: https://github.com/alexspeller
[@andersjanmyr]: https://github.com/andersjanmyr
[@antono]: https://github.com/antono
[@arr-ee]: https://github.com/arr-ee
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ unless ENV['TRAVIS']
gem 'redcarpet'
gem 'yajl-ruby'
gem 'rb-fsevent'
gem 'pry-debugger'
end
92 changes: 90 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.
* Runs the standard Jasmine test runner, so you can use [Jasminerice][] for integrating [Jasmine][] into the
[Rails asset pipeline][] and write your specs in [CoffeeScript][].

* Integrates [Istanbul](https://github.com/gotwarlost/istanbul) to instrument your code in the asset pipeline and
generate coverage reports.

* Custom console logger implementation for pretty printing JavaScript objects and DOM elements.

* Can be used to run [Jasmine-species](http://rudylattae.github.com/jasmine-species/) acceptance tests provided by
Expand Down Expand Up @@ -276,6 +279,7 @@ create a Rack configuration to spin up a mini-Rails app for testing:
```Ruby
require 'action_controller/railtie'
require 'jasminerice'
require 'guard/jasmine'
require 'sprockets/railtie'
require 'jquery-rails'

Expand Down Expand Up @@ -489,9 +493,85 @@ You can further customize the log output by implement one of these methods:
In addition, the console can log jQuery collections and outputs the HTML representation of the element by using the
jQuery `html()` method.

### Coverage options

Guard::Jasmine supports coverage reports generated by [Istanbul](https://github.com/gotwarlost/istanbul). You need to
have `istanbul` in your path in order to make this feature work. You can install it with NPM

```ruby
$ npm install istanbul
```

You also need to explicit enable the coverage support in the options:

```ruby
:coverage => :true # Enable/disable JavaScript coverage support
# default: :false
```

### Instrumentation

Istanbul needs to instrument the implementation files so that the execution path can be detected. Guard::Jasmine comes
with a tilt template that generates instrumented implementation files when using in the asset pipeline. If you do not
use asset pipeline, than you need to instrument your files on your own, either manually or by using something like
[Guard::Process](https://github.com/socialreferral/guard-process). You can get more information about the
instrumentation with `instanbul help instrument`.

**Important**: You need to clear the asset cache when you change this setting, so that already compiled assets will be
recompiled. Just use the Sprockets supplied Rake task:

```ruby
$ rake assets:clean
```

#### Check coverage

By default Guard::Jasmine just outputs the coverage when enable without any effect on the spec run result. You can
make Guard::Jasmine fail the spec run when a given threshold is not met. You can set the following thresholds:

```ruby
:statements_threshold => 95 # Statements coverage threshold
# default: 0

:functions_threshold => 85 # Functions coverage threshold
# default: 0

:branches_threshold => -10 # Branches coverage threshold
# default: 0

:lines_threshold => -15 # Lines coverage threshold
# default: 0
```

A positive threshold is taken to be the minimum percentage required, a negative threshold represents the maximum number
of uncovered entities allowed.

#### Coverage report

Guard::Jasmine always shows the Istanbul text report after a spec run that contains the coverage results per file. You
can also enable two more reports:

```ruby
:coverage_html => :true # Enable Istanbul HTML coverage report
# default: :false

:coverage_summary => :true # Enable Istanbul summary coverage report
# default: :false
```

The `:coverage_summary` options disables the detailed file based coverage report by a small summary coverage report.

Both of these results are more useful if they are run against the coverage data from a full spec run, so it's strongly
advised to enable the `:all_on_start` option.

With Jasmine in the asset pipeline all instrumented implementation files are available in the runtime and when you
execute a partial spec run it reports a lower coverage for the excluded files, since their associated specs aren't run.
Guard::Jasmine tries to work around this by merge only the coverage data for the changed files (Istanbul knows the file
name in opposite to Jasmine).

### System notifications options

These options affects what system notifications (growl, libnotify or notifu) are shown after a spec run:
These options affects what system notifications are shown after a spec run:

```ruby
:notifications => false # Show success and error notifications.
Expand Down Expand Up @@ -564,7 +644,15 @@ Options:
# Default: true
[--specdoc=SPECDOC] # Whether to show successes in the spec runner, either `always`, `never` or `failure`
# Default: always

[--coverage] # Whether to enable the coverage support or not
[--statements-threshold=N] # Statements coverage threshold
# Default: 0
[--functions-threshold=N] # Functions coverage threshold
# Default: 0
[--branches-threshold=N] # Branches coverage threshold
# Default: 0
[--lines-threshold=N] # Lines coverage threshold
# Default: 0
Run the Jasmine spec runner
```

Expand Down
66 changes: 40 additions & 26 deletions lib/guard/jasmine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,50 @@
require 'guard/guard'
require 'guard/watcher'

require 'guard/jasmine/jscoverage'

module Guard

# The Jasmine guard that gets notifications about the following
# Guard events: `start`, `stop`, `reload`, `run_all` and `run_on_change`.
#
class Jasmine < Guard

autoload :Inspector, 'guard/jasmine/inspector'
autoload :Runner, 'guard/jasmine/runner'
autoload :Server, 'guard/jasmine/server'
autoload :Util, 'guard/jasmine/util'
require 'guard/jasmine/coverage'
require 'guard/jasmine/inspector'
require 'guard/jasmine/runner'
require 'guard/jasmine/server'
require 'guard/jasmine/util'

extend Util
extend ::Guard::Jasmine::Util

attr_accessor :last_run_failed, :last_failed_paths, :run_all_options

DEFAULT_OPTIONS = {
:server => :auto,
:server_env => ENV['RAILS_ENV'] || 'development',
:server_timeout => 15,
:port => nil,
:rackup_config => nil,
:jasmine_url => nil,
:timeout => 10,
:spec_dir => 'spec/javascripts',
:notification => true,
:hide_success => false,
:all_on_start => true,
:keep_failed => true,
:clean => true,
:all_after_pass => true,
:max_error_notify => 3,
:specdoc => :failure,
:console => :failure,
:errors => :failure,
:focus => true
:server => :auto,
:server_env => ENV['RAILS_ENV'] || 'development',
:server_timeout => 15,
:port => nil,
:rackup_config => nil,
:jasmine_url => nil,
:timeout => 10,
:spec_dir => 'spec/javascripts',
:notification => true,
:hide_success => false,
:all_on_start => true,
:keep_failed => true,
:clean => true,
:all_after_pass => true,
:max_error_notify => 3,
:specdoc => :failure,
:console => :failure,
:errors => :failure,
:focus => true,
:coverage => false,
:coverage_html => false,
:coverage_summary => false,
:statements_threshold => 0,
:functions_threshold => 0,
:branches_threshold => 0,
:lines_threshold => 0
}

# Initialize Guard::Jasmine.
Expand All @@ -68,6 +74,13 @@ class Jasmine < Guard
# @option options [Symbol] :console options for the console.log output, either :always, :never or :failure
# @option options [Symbol] :errors options for the errors output, either :always, :never or :failure
# @option options [Symbol] :focus options for focus on failures in the specdoc
# @option options [Symbol] :coverage options for enable coverage support
# @option options [Symbol] :coverage_html options for enable coverage html support
# @option options [Symbol] :coverage_summary options for enable coverage summary support
# @option options [Symbol] :statements_threshold options for the statement coverage threshold
# @option options [Symbol] :functions_threshold options for the statement function threshold
# @option options [Symbol] :branches_threshold options for the statement branch threshold
# @option options [Symbol] :lines_threshold options for the statement lines threshold
# @option options [Hash] :run_all options overwrite options when run all specs
#
def initialize(watchers = [], options = { })
Expand Down Expand Up @@ -159,3 +172,4 @@ def run_on_changes(paths)

end
end

67 changes: 47 additions & 20 deletions lib/guard/jasmine/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ class CLI < Thor
:default => :always,
:desc => 'Whether to show successes in the spec runner, either `always`, `never` or `failure`'

method_option :coverage,
:type => :boolean,
:default => false,
:desc => 'Whether to enable the coverage support or not'

method_option :statements_threshold,
:type => :numeric,
:default => 0,
:desc => 'Statements coverage threshold'

method_option :functions_threshold,
:type => :numeric,
:default => 0,
:desc => 'Functions coverage threshold'

method_option :branches_threshold,
:type => :numeric,
:default => 0,
:desc => 'Branches coverage threshold'

method_option :lines_threshold,
:type => :numeric,
:default => 0,
:desc => 'Lines coverage threshold'

# Run the Guard::Jasmine::Runner with options from
# the command line.
#
Expand All @@ -100,26 +125,28 @@ class CLI < Thor
def spec(*paths)
paths = [options.spec_dir] if paths.empty?

runner_options = { }
runner_options[:port] = options.port || CLI.find_free_server_port
runner_options[:jasmine_url] = options.url || "http://localhost:#{ runner_options[:port] }/jasmine"
runner_options[:phantomjs_bin] = options.bin || CLI.which('phantomjs')
runner_options[:timeout] = options.timeout
runner_options[:server] = options.server.to_sym
runner_options[:server_env] = options.server_env
runner_options[:server_timeout] = options.server_timeout
runner_options[:rackup_config] = options.rackup_config
runner_options[:spec_dir] = options.spec_dir
runner_options[:console] = [:always, :never, :failure].include?(options.console.to_sym) ? options.console.to_sym : :failure
runner_options[:errors] = [:always, :never, :failure].include?(options.errors.to_sym) ? options.errors.to_sym : :failure
runner_options[:specdoc] = [:always, :never, :failure].include?(options.specdoc.to_sym) ? options.specdoc.to_sym : :always
runner_options[:focus] = options.focus


runner_options[:notification] = false
runner_options[:hide_success] = true

runner_options[:max_error_notify] = 0
runner_options = { }
runner_options[:port] = options.port || CLI.find_free_server_port
runner_options[:jasmine_url] = options.url || "http://localhost:#{ runner_options[:port] }/jasmine"
runner_options[:phantomjs_bin] = options.bin || CLI.which('phantomjs')
runner_options[:timeout] = options.timeout
runner_options[:server] = options.server.to_sym
runner_options[:server_env] = options.server_env
runner_options[:server_timeout] = options.server_timeout
runner_options[:rackup_config] = options.rackup_config
runner_options[:spec_dir] = options.spec_dir
runner_options[:console] = [:always, :never, :failure].include?(options.console.to_sym) ? options.console.to_sym : :failure
runner_options[:errors] = [:always, :never, :failure].include?(options.errors.to_sym) ? options.errors.to_sym : :failure
runner_options[:specdoc] = [:always, :never, :failure].include?(options.specdoc.to_sym) ? options.specdoc.to_sym : :always
runner_options[:focus] = options.focus
runner_options[:coverage] = options.coverage
runner_options[:statements_threshold] = options.statements_threshold
runner_options[:functions_threshold] = options.functions_threshold
runner_options[:branches_threshold] = options.branches_threshold
runner_options[:lines_threshold] = options.lines_threshold
runner_options[:notification] = false
runner_options[:hide_success] = true
runner_options[:max_error_notify] = 0

if CLI.phantomjs_bin_valid?(runner_options[:phantomjs_bin])
catch(:task_has_failed) do
Expand Down
Loading

0 comments on commit 18a1689

Please sign in to comment.