chefspec-coveragereports 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +119 -0
- data/lib/chefspec/coverage.rb +35 -0
- data/lib/chefspec/coveragereports.rb +122 -0
- data/lib/chefspec/coveragereports/version.rb +13 -0
- data/templates/json.erb +1 -0
- metadata +132 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Anthony Spring
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# ChefSpec::CoverageReports
|
2
|
+
|
3
|
+
Provides a generic interface to creating ChefSpec coverage reports, including a default JSON template.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'chefspec-coveragereports'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install chefspec-coveragereports
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To enable the Coverage Reports functionality, you must include the following inside of your spec_helper:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'chefspec/coveragereports'
|
27
|
+
```
|
28
|
+
|
29
|
+
With this included you can now tell the Coverage Reports what reports to generate and where to place the reports.
|
30
|
+
|
31
|
+
#### Using one of the included templates
|
32
|
+
|
33
|
+
To utilize one of the included Erubis templates you can use the following:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
ChefSpec::CoverageReports.add('json', 'coverage.json')
|
37
|
+
```
|
38
|
+
|
39
|
+
This will utilize the built in json template, and create a file named coverage.json.
|
40
|
+
|
41
|
+
#### Proving your own template
|
42
|
+
|
43
|
+
To utilize your own Erubis template you can use the following:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
ChefSpec::CoverageReports.add_custom('some/path/template.erb', 'coverage.report')
|
47
|
+
```
|
48
|
+
|
49
|
+
Where you provide the path to the template, and the output file for the report.
|
50
|
+
|
51
|
+
## Template Functionality
|
52
|
+
|
53
|
+
Coverage Reports exposes a hash called `@coverage` that can be used to create your own custom Erubis templates.
|
54
|
+
|
55
|
+
This hash provides full access to the raw coverage data generated by ChefSpec, as well as some already processed data.
|
56
|
+
|
57
|
+
### raw
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
@coverage['raw']
|
61
|
+
```
|
62
|
+
|
63
|
+
Provides full access to the array of raw data generated by ChefSpec
|
64
|
+
|
65
|
+
### coverage
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
@coverage['coverage']
|
69
|
+
```
|
70
|
+
|
71
|
+
Provides acccess to the data processed by Coverage Reports.
|
72
|
+
|
73
|
+
##### files
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
@coverage['coverage']['files']
|
77
|
+
```
|
78
|
+
|
79
|
+
Provides access to a hash of all of the files and the resources observed inside of them.
|
80
|
+
|
81
|
+
##### resources - all
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
@coverage['coverage']['resources']['all']
|
85
|
+
```
|
86
|
+
|
87
|
+
Provides access to a hash of all of the resources, keyed by name.
|
88
|
+
|
89
|
+
##### resources - covered
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
@coverage['coverage']['resources']['covered']
|
93
|
+
```
|
94
|
+
|
95
|
+
Provides access to a hash of all of the resources that were covered, keyed by name.
|
96
|
+
|
97
|
+
##### resources - uncovered
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
@coverage['coverage']['resources']['uncovered']
|
101
|
+
```
|
102
|
+
|
103
|
+
Provides access to a hash of all of the resources that were **not** covered, keyed by name.
|
104
|
+
|
105
|
+
##### totals
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
@coverage['coverage']['totals']
|
109
|
+
```
|
110
|
+
|
111
|
+
Provides a set of totals to help make reporting easier, including total resources, covered and uncovered resource counts, as well as percent coverage.
|
112
|
+
|
113
|
+
## Contributing
|
114
|
+
|
115
|
+
1. Fork it ( https://github.com/[my-github-username]/chefspec-reports/fork )
|
116
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
117
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
118
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
119
|
+
5. Create a new Pull Request
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'chefspec/coverage'
|
2
|
+
|
3
|
+
ChefSpec::Coverage.class_eval do
|
4
|
+
def report!
|
5
|
+
# Borrowed from simplecov#41
|
6
|
+
#
|
7
|
+
# If an exception is thrown that isn't a "SystemExit", we need to capture
|
8
|
+
# that error and re-raise.
|
9
|
+
if $ERROR_INFO
|
10
|
+
exit_status = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : ChefSpec::Coverage::EXIT_FAILURE
|
11
|
+
else
|
12
|
+
exit_status = ChefSpec::Coverage::EXIT_SUCCESS
|
13
|
+
end
|
14
|
+
|
15
|
+
report = {}.tap do |h|
|
16
|
+
h[:total] = @collection.size
|
17
|
+
h[:touched] = @collection.count { |_, resource| resource.touched? }
|
18
|
+
h[:coverage] = ((h[:touched] / h[:total].to_f) * 100).round(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
report[:untouched_resources] = @collection.map do |_, resource|
|
22
|
+
resource unless resource.touched?
|
23
|
+
end.compact
|
24
|
+
|
25
|
+
template = ChefSpec.root.join('templates', 'coverage', 'human.erb')
|
26
|
+
erb = Erubis::Eruby.new(File.read(template))
|
27
|
+
puts erb.evaluate(report)
|
28
|
+
|
29
|
+
# Generate the coverage reports
|
30
|
+
ChefSpec::CoverageReports.generate_reports(@collection)
|
31
|
+
|
32
|
+
# Ensure we exit correctly (#351)
|
33
|
+
Kernel.exit(exit_status) if exit_status && exit_status > 0
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'chefspec'
|
2
|
+
require 'chefspec/coveragereports/version'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module ChefSpec
|
6
|
+
class CoverageReports
|
7
|
+
class << self
|
8
|
+
def method_added(name)
|
9
|
+
# Only delegate public methods
|
10
|
+
if method_defined?(name)
|
11
|
+
instance_eval <<-EOH, __FILE__, __LINE__ + 1
|
12
|
+
def #{name}(*args, &block)
|
13
|
+
instance.public_send(:#{name}, *args, &block)
|
14
|
+
end
|
15
|
+
EOH
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
include Singleton
|
21
|
+
|
22
|
+
attr_reader :reports
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@reports = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def add(type, output_file)
|
29
|
+
reports[root.join('templates', "#{type}.erb")] = output_file
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_custom(template, output_file)
|
33
|
+
reports[template] = output_file
|
34
|
+
end
|
35
|
+
|
36
|
+
def clear_reports
|
37
|
+
@reports = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(type)
|
41
|
+
reports[type] = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def generate_reports(data)
|
45
|
+
@coverage = {}
|
46
|
+
@coverage['raw'] = data
|
47
|
+
@coverage['coverage'] = process_report_data(data)
|
48
|
+
|
49
|
+
reports.each do |template, output_file|
|
50
|
+
erb = Erubis::Eruby.new(File.read(template))
|
51
|
+
|
52
|
+
# Create the output directory if it doesnt exist
|
53
|
+
dirname = File.dirname(output_file)
|
54
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
55
|
+
|
56
|
+
File.open(output_file, 'w') { |f| f.write(erb.evaluate(@coverage)) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def root
|
63
|
+
@root ||= Pathname.new(File.expand_path('../../../', __FILE__))
|
64
|
+
end
|
65
|
+
|
66
|
+
def process_report_data(data)
|
67
|
+
results = {}
|
68
|
+
results['files'] = {}
|
69
|
+
results['resources'] = {}
|
70
|
+
results['resources']['all'] = {}
|
71
|
+
results['resources']['covered'] = {}
|
72
|
+
results['resources']['uncovered'] = {}
|
73
|
+
results['totals'] = {}
|
74
|
+
|
75
|
+
# Process the report data
|
76
|
+
data.map do |name, resource|
|
77
|
+
resource_hash = generate_resource_hash(resource)
|
78
|
+
|
79
|
+
# Store the file information
|
80
|
+
results['files'][resource.source_file] ||= {}
|
81
|
+
results['files'][resource.source_file][name] = resource_hash
|
82
|
+
|
83
|
+
# Store the resources information
|
84
|
+
results['resources']['all'][name] = resource_hash
|
85
|
+
results['resources']['covered'][name] = resource_hash if resource.touched?
|
86
|
+
results['resources']['uncovered'][name] = resource_hash unless resource.touched?
|
87
|
+
end
|
88
|
+
|
89
|
+
# Sort the results
|
90
|
+
results['files'].sort
|
91
|
+
results['files'].each do |f, _|
|
92
|
+
results['files'][f].sort
|
93
|
+
end
|
94
|
+
results['resources']['all'].sort
|
95
|
+
results['resources']['covered'].sort
|
96
|
+
results['resources']['uncovered'].sort
|
97
|
+
|
98
|
+
# Calculate the derived totals
|
99
|
+
results['totals']['resources'] = results['resources']['all'].size
|
100
|
+
results['totals']['covered'] = results['resources']['covered'].size
|
101
|
+
results['totals']['uncovered'] = results['resources']['uncovered'].size
|
102
|
+
results['totals']['percent'] = ((results['totals']['covered'] / results['totals']['resources'].to_f) * 100).round(2)
|
103
|
+
results['totals']['percent'] = 0 if results['totals']['percent'].nan?
|
104
|
+
results['totals']['percent'] = 100 if results['totals']['percent'].infinite?
|
105
|
+
|
106
|
+
results
|
107
|
+
end
|
108
|
+
|
109
|
+
def generate_resource_hash(resource)
|
110
|
+
result = {}
|
111
|
+
|
112
|
+
result['name'] = resource.to_s
|
113
|
+
result['source'] = resource.source_file
|
114
|
+
result['line'] = resource.source_line
|
115
|
+
result['covered'] = resource.touched?
|
116
|
+
|
117
|
+
result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
require_relative 'coverage'
|
data/templates/json.erb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<%= JSON.pretty_generate(@coverage) + "\n" %>
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chefspec-coveragereports
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Anthony Spring
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
- !binary |-
|
13
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwakNDQW82Z0F3SUJB
|
14
|
+
Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREJNTVEwd0N3WURWUVFEREFSMGIy
|
15
|
+
NTUKTVNZd0pBWUtDWkltaVpQeUxHUUJHUllXY0c5eWEyTm9iM0J6WVc1a2NH
|
16
|
+
RnBiblJqYUdsd2N6RVRNQkVHQ2dtUwpKb21UOGl4a0FSa1dBMk52YlRBZUZ3
|
17
|
+
MHhOVEF6TWpneU1qUTVOREJhRncweE5qQXpNamN5TWpRNU5EQmFNRXd4CkRU
|
18
|
+
QUxCZ05WQkFNTUJIUnZibmt4SmpBa0Jnb0praWFKay9Jc1pBRVpGaFp3YjNK
|
19
|
+
clkyaHZjSE5oYm1Sd1lXbHUKZEdOb2FYQnpNUk13RVFZS0NaSW1pWlB5TEdR
|
20
|
+
QkdSWURZMjl0TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQwpBUThBTUlJ
|
21
|
+
QkNnS0NBUUVBcUxDMzVTYmFLQnQ3YjdISncxdDh0ejRrYStSNDl5cjBrNFNx
|
22
|
+
eUxGd0JiOXRHSVBKCm9ORWNtUzJWL05pV0l0bWtlLzcrdVphaklROW9XKzlr
|
23
|
+
aDJJdzE1bDQ5S0JobkZDcTNrK2IxeVRTVm1OZXBLbXoKN21tdDA1Rjg4VkZ6
|
24
|
+
aDRkU2hyZjRMdnlGT1JuQVMyTmJVblNvTDBhMFUzVS9ielMyWVhGbGROdkdE
|
25
|
+
aTVIdVZ2WApvK21xMHpXemJnOERjdWhVUjVHWFA2dnNVVzJZVFErTURvRU1n
|
26
|
+
enNwcDRwTUNFbDRNc2d4UzhTb3NTRi9yQXl6Cml6bndXOGN5REVhNDFjUUlL
|
27
|
+
UzRySWkySnpwdkdKYjJVd0JNTXVXaGthRG84MUR4cGJaRktmSGo2cm1zK0Zi
|
28
|
+
OEMKVFhNUVpvd0JpR05DQ1lVS3ZrT3JXTXVqWW0zVWxIY2RCS0NOelFJREFR
|
29
|
+
QUJvNEdTTUlHUE1Ba0dBMVVkRXdRQwpNQUF3Q3dZRFZSMFBCQVFEQWdTd01C
|
30
|
+
MEdBMVVkRGdRV0JCVERheUdjT1Y1cXB1bnk2ejdjYVRjcW11MzJZakFxCkJn
|
31
|
+
TlZIUkVFSXpBaGdSOTBiMjU1UUhCdmNtdGphRzl3YzJGdVpIQmhhVzUwWTJo
|
32
|
+
cGNITXVZMjl0TUNvR0ExVWQKRWdRak1DR0JIM1J2Ym5sQWNHOXlhMk5vYjNC
|
33
|
+
ellXNWtjR0ZwYm5SamFHbHdjeTVqYjIwd0RRWUpLb1pJaHZjTgpBUUVGQlFB
|
34
|
+
RGdnRUJBSFJrL3gxTTAwd0o3OHVkTzlROUZFemw2ajhMWnF3NHoxdVRlZW1J
|
35
|
+
aHVlMlB2NWpWV0cxClF3ZlFsQ1pQKzFQajZiWFl2aWtrQkhoN1FSVkgxVFZM
|
36
|
+
cHVnTE5YY3BvVnNwVnhITnVvdTRjNmhHa0VlRTBBYVYKVVlqcGtTcTFSNGt5
|
37
|
+
Qy9ETzVmSU4rRGpNZDcvNFhDZXBNUWJLdWt6R2Yxait0QkgvclJEWkJEMXlO
|
38
|
+
Y245MHZOYQpXMGRmY0dLOW82Q05YU3NPcXVCeDd6R25uS2NGWGlrcjU1Z1Bx
|
39
|
+
VW5qdWxSQnFVT21LN3lYUlgxL2h6R3RrenVwCnRWM0ZWcmVPRmlpWFo2eXhE
|
40
|
+
djVxdUNQdUh0bzZmWnh0d0RTb0xlaWVHeXJNVDgwaEFTMW5FT1dWWVh4V3BS
|
41
|
+
VmEKWEJRZVBYREhnZmw1SkRMMDVLSXowK3grLzVkRnFsTW5XSVE9Ci0tLS0t
|
42
|
+
RU5EIENFUlRJRklDQVRFLS0tLS0K
|
43
|
+
date: 2015-03-28 00:00:00.000000000 Z
|
44
|
+
dependencies:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: chefspec
|
47
|
+
requirement: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '4.0'
|
53
|
+
type: :runtime
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: bundler
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.7'
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: rake
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ~>
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '10.0'
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ~>
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '10.0'
|
93
|
+
description: ChefSpec Coverage Reports
|
94
|
+
email:
|
95
|
+
- tony@porkchopsandpaintchips.com
|
96
|
+
executables: []
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- lib/chefspec/coverage.rb
|
101
|
+
- lib/chefspec/coveragereports/version.rb
|
102
|
+
- lib/chefspec/coveragereports.rb
|
103
|
+
- templates/json.erb
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
homepage: https://github.com/aspring/chefspec-coveragereports
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 1.8.23.2
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: ChefSpec Coverage Reports
|
131
|
+
test_files: []
|
132
|
+
has_rdoc:
|
metadata.gz.sig
ADDED
Binary file
|