duvet 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ cov
23
+ doc
24
+ .yardoc
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Joshua Hawxwell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # duvet
2
+
3
+ Install with
4
+
5
+ (sudo) gem install duvet
6
+
7
+ Then add this to the __very__ top of your `test/helper.rb` (or similar)
8
+
9
+ require 'duvet
10
+ Duvet.start
11
+
12
+ You can change the defaults by passing an options hash to Duvet.start, eg
13
+
14
+ Duvet.start({:dir => 'coverage', :filter => 'app/lib'})
15
+
16
+ `:dir` is the directory to write the coverage to.
17
+ `:filter` allows you to display only coverage for files that include the string.
18
+
19
+ ## Note on Patches/Pull Requests
20
+
21
+ * Fork the project.
22
+ * Make your feature addition or bug fix.
23
+ * Add tests for it. This is important so I don't break it in a
24
+ future version unintentionally.
25
+ * Commit, do not mess with rakefile, version, or history.
26
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
27
+ * Send me a pull request. Bonus points for topic branches.
28
+
29
+ ## Copyright
30
+
31
+ Copyright (c) 2010 Joshua Hawxwell. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "duvet"
8
+ gem.summary = %Q{Duvet a simple code coverage tool for 1.9}
9
+ gem.description = %Q{Duvet a simple code coverage tool for 1.9}
10
+ gem.email = "m@hawx.me"
11
+ gem.homepage = "http://github.com/hawx/duvet"
12
+ gem.authors = ["Joshua Hawxwell"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "yard", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ begin
47
+ require 'yard'
48
+ YARD::Rake::YardocTask.new
49
+ rescue LoadError
50
+ task :yardoc do
51
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
52
+ end
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/bin/duvet ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A command line tool for coverage testing, I'm not sure if this
4
+ # will even work but it is worth a try!
5
+ #
6
+ # Example:
7
+ # duvet test/test_class.rb
8
+ #
9
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
+
11
+ require 'clive'
12
+ require 'duvet'
13
+
14
+ opts = {:dir => 'cov', :style => 'rcov'}
15
+ c = Clive.new do
16
+
17
+ header "Usage: duvet [options] [paths]"
18
+
19
+ flag(:css, "PATH", "Use custom css file") do |i|
20
+ opts[:css] = i
21
+ end
22
+
23
+ flag(:s, :style, "ARG", "Choose style") do |i|
24
+ opts[:style] = i
25
+ end
26
+
27
+ flag(:d, :dir, "PATH", "Directory to write coverage results") do |i|
28
+ opts[:dir] = i
29
+ end
30
+
31
+ flag(:f, :filter, "FILTER", "Use a filter to see only needed results") do |i|
32
+ opts[:filter] = i
33
+ end
34
+
35
+ end
36
+
37
+ # Start coverage, then require paths
38
+ def run(paths, opts)
39
+ Duvet.start(opts)
40
+ paths.each do |p|
41
+ require p
42
+ end
43
+ end
44
+
45
+ args = c.parse(ARGV)
46
+ run(args, opts)
data/duvet.gemspec ADDED
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{duvet}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Joshua Hawxwell"]
12
+ s.date = %q{2010-09-01}
13
+ s.default_executable = %q{duvet}
14
+ s.description = %q{Duvet a simple code coverage tool for 1.9}
15
+ s.email = %q{m@hawx.me}
16
+ s.executables = ["duvet"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/duvet",
29
+ "duvet.gemspec",
30
+ "lib/duvet.rb",
31
+ "lib/duvet/cov.rb",
32
+ "lib/duvet/covs.rb",
33
+ "lib/duvet/ext.rb",
34
+ "lib/duvet/resources/jquery.js",
35
+ "lib/duvet/resources/main.js",
36
+ "lib/duvet/resources/plugins.js",
37
+ "lib/duvet/resources/rcov.sass",
38
+ "lib/duvet/templates/file.erb",
39
+ "lib/duvet/templates/index.erb",
40
+ "test/helper.rb",
41
+ "test/test_duvet.rb",
42
+ "test_duvet/lib/klass.rb",
43
+ "test_duvet/lib/run.rb",
44
+ "test_duvet/test/test_all.rb"
45
+ ]
46
+ s.homepage = %q{http://github.com/hawx/duvet}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.7}
50
+ s.summary = %q{Duvet a simple code coverage tool for 1.9}
51
+ s.test_files = [
52
+ "test/helper.rb",
53
+ "test/test_duvet.rb"
54
+ ]
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
62
+ s.add_development_dependency(%q<yard>, [">= 0"])
63
+ else
64
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ s.add_dependency(%q<yard>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
69
+ s.add_dependency(%q<yard>, [">= 0"])
70
+ end
71
+ end
72
+
data/lib/duvet.rb ADDED
@@ -0,0 +1,86 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ # Add this to test/helper.rb at the before __anything__ else
4
+ #
5
+ # require 'duvet'
6
+ # Duvet.start
7
+ #
8
+ require 'coverage'
9
+ require 'ostruct'
10
+ require 'erubis'
11
+ require 'pathname'
12
+ require 'sass'
13
+
14
+ require 'duvet/ext'
15
+ require 'duvet/covs'
16
+ require 'duvet/cov'
17
+
18
+
19
+ module Duvet
20
+
21
+ attr_accessor :opts
22
+
23
+ DEFAULTS = {:dir => 'cov', :style => 'rcov'}
24
+
25
+ # Start tracking
26
+ def self.start(opts={})
27
+ @opts = DEFAULTS.merge(opts)
28
+
29
+ Coverage.start
30
+ @running = true
31
+ end
32
+
33
+ # Get result
34
+ def self.result
35
+ cov = Coverage.result if running?
36
+ if @opts[:filter]
37
+ filtered = {}
38
+ cov.each do |k, v|
39
+ if k.include?(@opts[:filter])
40
+ filtered[k] = v
41
+ end
42
+ end
43
+ cov = filtered
44
+ end
45
+ @result ||= Duvet::Covs.new(cov)
46
+ ensure
47
+ @running = false
48
+ end
49
+
50
+ # Write results
51
+ def self.write
52
+ self.result.write(@opts[:dir], @opts[:style]) if running?
53
+ end
54
+
55
+ # Proc to call when exiting
56
+ # @todo Allow user to override block used
57
+ def self.at_exit
58
+ Proc.new { self.write }
59
+ end
60
+
61
+ # @return [Boolean] whether coverage is running
62
+ def self.running?
63
+ @running
64
+ end
65
+
66
+ # Reads the current version from VERSION
67
+ #
68
+ # @return [String] current version
69
+ def self.version
70
+ File.read( File.join(File.dirname(__FILE__), '..', 'VERSION') )
71
+ end
72
+
73
+ # @return [Hash] hash to merge for templating
74
+ def self.template_hash
75
+ {
76
+ 'time' => Time.now,
77
+ 'version' => self.version,
78
+ 'name' => 'duvet'
79
+ }
80
+ end
81
+
82
+ end
83
+
84
+ at_exit do
85
+ Duvet.at_exit.call
86
+ end
data/lib/duvet/cov.rb ADDED
@@ -0,0 +1,118 @@
1
+ module Duvet
2
+ class Cov
3
+ attr_accessor :cov, :path
4
+
5
+ def initialize(path, cov)
6
+ if path.include?(Dir.pwd)
7
+ @path = path.to_p.relative_path_from(Pathname.pwd)
8
+ else
9
+ @path = path.to_p
10
+ end
11
+
12
+ @cov = cov
13
+ write
14
+ end
15
+
16
+ # @return [Integer] number of lines in file
17
+ def lines
18
+ @cov.length
19
+ end
20
+
21
+ # @return [Array] all lines which can be executed
22
+ def code_lines
23
+ @cov.reject {|i| i.nil?}
24
+ end
25
+
26
+ # @return [Integer] number of lines of code that can be executed
27
+ def lines_of_code
28
+ code_lines.length
29
+ end
30
+
31
+ # Gives a fraction from 0 to 1 of how many lines of code have
32
+ # been executed. It ignores all lines that couldn't be executed
33
+ # such as comments.
34
+ #
35
+ # @return [Integer] lines of code executed as a fraction
36
+ def code_coverage
37
+ ran_lines = code_lines.reject {|i| i.zero?}.length
38
+ ran_lines.to_f / lines_of_code.to_f
39
+ end
40
+
41
+ # @return [String] #code_coverage as ??.??%
42
+ def code_coverage_percent
43
+ "%.2f%" % (code_coverage*100)
44
+ end
45
+
46
+ # Similar to #code_coverage but counts all lines, executable
47
+ # or not.
48
+ #
49
+ # @return [Integer] lines executed as a fraction
50
+ def total_coverage
51
+ ran_lines = @cov.reject {|i| i.nil? || i.zero?}.length
52
+ ran_lines.to_f / lines.to_f
53
+ end
54
+
55
+ # @return [String] #total_coverage as ??.??%
56
+ def total_coverage_percent
57
+ "%.2f%" % (total_coverage*100)
58
+ end
59
+
60
+ # Creates a report showing the source code.
61
+ #
62
+ # @return [String] a report showing line number, source and
63
+ # times run
64
+ def source_report
65
+ source = @path.readlines
66
+ str = ""
67
+ source.zip(@cov).each_with_index do |a, i|
68
+ line, count = a[0], a[1]
69
+ str << "#{i}| #{line.gsub("\n", "")}"
70
+ str << " #=> #{count}" if count
71
+ str << "\n"
72
+ end
73
+ str
74
+ end
75
+
76
+ # @return [String]
77
+ def report
78
+ str = "For #{@path}\n\n" << source_report << "\n"
79
+ str << "total coverage: #{total_coverage}\n"
80
+ str << "code coverage: #{code_coverage}\n"
81
+ str
82
+ end
83
+
84
+ # @return [Hash] a hash of data for templating
85
+ def data
86
+ {
87
+ "file" => {
88
+ "path" => @path,
89
+ "url" => @path.file_name + '.html',
90
+ "source" => @path.readlines,
91
+ "lines" => lines,
92
+ "lines_code" => lines_of_code
93
+ },
94
+ "coverage" => {
95
+ "code" => code_coverage_percent,
96
+ "total" => total_coverage_percent,
97
+ "lines" => @cov
98
+ }
99
+ }
100
+ end
101
+
102
+ # Formats the coverage for the file to be written to a html
103
+ # file, then viewed in a web browser.
104
+ #
105
+ # @return [String]
106
+ def format
107
+ template = File.read(File.join( File.dirname(__FILE__), "templates", "file.erb" ))
108
+ e = Erubis::Eruby.new(template).result(Duvet.template_hash.merge(self.data))
109
+ e
110
+ end
111
+
112
+ def write(dir='cov')
113
+ f = File.new((dir.to_p + @path.file_name).to_s + '.html', "w" )
114
+ f.write(format)
115
+ end
116
+
117
+ end
118
+ end