duvet 0.3.3 → 0.4.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/LICENSE +1 -1
- data/README.md +26 -9
- data/Rakefile +13 -2
- data/lib/duvet.rb +101 -43
- data/lib/duvet/cov.rb +58 -65
- data/lib/duvet/covs.rb +25 -37
- data/lib/duvet/version.rb +2 -2
- data/spec/duvet/cov_spec.rb +91 -0
- data/spec/duvet/covs_spec.rb +57 -0
- data/spec/duvet_spec.rb +81 -0
- data/{test → spec}/helper.rb +2 -8
- data/templates/css/styles.css +129 -0
- data/templates/html/file.erb +21 -22
- data/templates/html/index.erb +14 -15
- metadata +19 -44
- data/lib/duvet/core_ext.rb +0 -17
- data/test/test_core_ext.rb +0 -13
- data/test/test_cov.rb +0 -76
- data/test/test_covs.rb +0 -67
- data/test/test_duvet.rb +0 -17
data/lib/duvet/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Duvet
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
2
|
+
VERSION = '0.4.0'
|
3
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
describe Duvet::Cov do
|
4
|
+
|
5
|
+
let(:lines) { [5, 2, nil, 2, 4, 3, 0, 0, 0, nil] }
|
6
|
+
subject { Duvet::Cov.new('lib/duvet.rb', lines) }
|
7
|
+
|
8
|
+
describe '#path' do
|
9
|
+
it 'returns the cleaned path' do
|
10
|
+
cov = Duvet::Cov.new(Dir.pwd + '/test.rb', [])
|
11
|
+
cov.path.must_equal Pathname.new('test.rb')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#lines' do
|
16
|
+
it 'returns the passed coverage data' do
|
17
|
+
subject.lines.must_equal lines
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#code_lines' do
|
22
|
+
it 'returns lines which can be exectued' do
|
23
|
+
subject.code_lines.must_equal [5, 2, 2, 4, 3, 0, 0, 0]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#ran_lines' do
|
28
|
+
it 'returns lines which were executed' do
|
29
|
+
subject.ran_lines.must_equal [5, 2, 2, 4, 3]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
describe '#total_coverage' do
|
35
|
+
it 'returns the ratio of lines which were executed' do
|
36
|
+
subject.total_coverage.must_equal 0.5
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#code_coverage' do
|
41
|
+
it 'returns the ratio of executable lines which were executed' do
|
42
|
+
subject.code_coverage.must_equal 0.625
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#percent' do
|
47
|
+
it 'returns a number as a 4-digit (ie. ??.??) percentage' do
|
48
|
+
subject.percent(0.123456789).must_equal "12.35%"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#report' do
|
53
|
+
it 'generates a simple textual report of coverage' do
|
54
|
+
subject.report.must_equal <<EOS
|
55
|
+
lib/duvet.rb
|
56
|
+
total: 50.00%
|
57
|
+
code: 62.50%
|
58
|
+
EOS
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#data' do
|
63
|
+
it 'contains the necessary template data' do
|
64
|
+
subject.path.stubs(:readlines).returns("code and code and code")
|
65
|
+
|
66
|
+
subject.data.must_equal file: {
|
67
|
+
path: 'lib/duvet.rb',
|
68
|
+
url: 'lib/duvet.html',
|
69
|
+
root: '../',
|
70
|
+
source: 'code and code and code',
|
71
|
+
},
|
72
|
+
lines: {
|
73
|
+
total: 10,
|
74
|
+
code: 8,
|
75
|
+
ran: 5
|
76
|
+
},
|
77
|
+
coverage: {
|
78
|
+
code: '62.50%',
|
79
|
+
total: '50.00%',
|
80
|
+
lines: lines
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#write' do
|
86
|
+
it 'writes the file' do
|
87
|
+
Duvet.expects(:write).with(subject.data, 'html/file.erb')
|
88
|
+
subject.write
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
describe Duvet::Covs do
|
4
|
+
|
5
|
+
let(:files) {
|
6
|
+
{
|
7
|
+
'lib/duvet.rb' => [3, 2, 1, 0, nil],
|
8
|
+
'lib/duvet/cov.rb' => [nil, nil, 0, 1, 2]
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
subject { Duvet::Covs.from_data files }
|
13
|
+
|
14
|
+
describe '.from_data' do
|
15
|
+
it 'converts data to Cov instances' do
|
16
|
+
subject.each do |cov|
|
17
|
+
cov.must_be_kind_of Duvet::Cov
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#report' do
|
23
|
+
it 'creates a report' do
|
24
|
+
subject.report.must_equal <<EOS
|
25
|
+
lib/duvet.rb
|
26
|
+
total: 60.00%
|
27
|
+
code: 75.00%
|
28
|
+
|
29
|
+
lib/duvet/cov.rb
|
30
|
+
total: 40.00%
|
31
|
+
code: 66.67%
|
32
|
+
|
33
|
+
EOS
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#data' do
|
38
|
+
it 'populates the data' do
|
39
|
+
subject.data.must_include :files
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#write' do
|
44
|
+
it 'writes the index and individual covs' do
|
45
|
+
subject.each {|i| i.expects(:write) }
|
46
|
+
Duvet.expects(:write).with(subject.data, 'html/index.erb')
|
47
|
+
|
48
|
+
subject.write
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'warns if no coverage to write' do
|
52
|
+
empty = Duvet::Covs.new
|
53
|
+
-> { empty.write }.must_output nil, "No files to create coverage for.\n"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/spec/duvet_spec.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
describe Duvet do
|
4
|
+
|
5
|
+
before { Coverage.stubs(:start) }
|
6
|
+
subject { Duvet.dup }
|
7
|
+
|
8
|
+
describe '#start' do
|
9
|
+
it 'makes sure :filter is a regexp' do
|
10
|
+
subject.start :filter => 'str'
|
11
|
+
subject.opts[:filter].must_be_kind_of Regexp
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'starts Coverage' do
|
15
|
+
Coverage.expects(:start)
|
16
|
+
subject.start
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#result' do
|
21
|
+
it 'filters the results' do
|
22
|
+
Coverage.expects(:result).returns({'a/b.c' => [], 'a/e.f' => [], 'g/h.i' => []})
|
23
|
+
subject.start :filter => 'a/e'
|
24
|
+
|
25
|
+
subject.result.map(&:path).map(&:to_s).must_equal ['a/e.f']
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns a Covs instance' do
|
29
|
+
Coverage.stubs(:result).returns({'a/b.c' => []})
|
30
|
+
subject.result.must_be_kind_of Duvet::Covs
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#format' do
|
35
|
+
it 'renders a file from the data and template given' do
|
36
|
+
Pathname.any_instance.stubs(:read).returns("The magic number is <%= a %>")
|
37
|
+
r = subject.format({a: 1}, 'template.erb')
|
38
|
+
r.must_equal "The magic number is 1"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#write' do
|
43
|
+
it 'formats then writes a file' do
|
44
|
+
formatted = Object.new
|
45
|
+
data = {file: {url: 'somewhere/file.html'}}
|
46
|
+
subject.expects(:format).with(data, 'template').returns(formatted)
|
47
|
+
subject.expects(:write_file).with(formatted, 'somewhere/file.html')
|
48
|
+
|
49
|
+
subject.write data, 'template'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#write_file' do
|
54
|
+
it 'writes a file' do
|
55
|
+
File.expects(:open).with(Pathname.new('cov/somewhere/file.html'), 'w')
|
56
|
+
subject.write_file 'text', 'somewhere/file.html'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#write_resources' do
|
61
|
+
it 'writes the resources' do
|
62
|
+
subject.stubs(:write_file)
|
63
|
+
4.times { subject.expects(:write_file) }
|
64
|
+
|
65
|
+
subject.write_resources
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#finish' do
|
70
|
+
it 'makes the directory, writes the results and resources' do
|
71
|
+
FileUtils.expects(:mkdir_p).with(subject.opts[:dir])
|
72
|
+
obj = mock()
|
73
|
+
subject.expects(:result).returns(obj)
|
74
|
+
obj.expects(:write)
|
75
|
+
subject.expects(:write_resources)
|
76
|
+
|
77
|
+
subject.finish
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/{test → spec}/helper.rb
RENAMED
@@ -7,13 +7,7 @@ Coverage.start
|
|
7
7
|
require_relative '../lib/duvet'
|
8
8
|
Duvet.start :filter => 'lib/duvet'
|
9
9
|
|
10
|
-
require 'minitest/
|
10
|
+
require 'minitest/autorun'
|
11
11
|
require 'minitest/pride'
|
12
12
|
|
13
|
-
require '
|
14
|
-
class MiniTest::Unit::TestCase
|
15
|
-
include RR::Adapters::TestUnit
|
16
|
-
end
|
17
|
-
|
18
|
-
MiniTest::Unit.autorun
|
19
|
-
|
13
|
+
require 'mocha'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
@charset "UTF-8";
|
2
|
+
html {
|
3
|
+
margin: 0;
|
4
|
+
padding: 0;
|
5
|
+
width: 100%; }
|
6
|
+
|
7
|
+
body {
|
8
|
+
background: #f4f2ed;
|
9
|
+
font: 12px/1.3em Helvetica;
|
10
|
+
margin: 8px; }
|
11
|
+
|
12
|
+
a {
|
13
|
+
text-decoration: none; }
|
14
|
+
|
15
|
+
header {
|
16
|
+
margin: 2em 0.5em;
|
17
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); }
|
18
|
+
header h1, header h1 a {
|
19
|
+
color: #333333; }
|
20
|
+
header h2 {
|
21
|
+
color: #999999;
|
22
|
+
font-size: 16px; }
|
23
|
+
|
24
|
+
#filter {
|
25
|
+
position: absolute;
|
26
|
+
top: 20px;
|
27
|
+
right: 8px;
|
28
|
+
border: 1px solid #787878;
|
29
|
+
background: #f0f0f0;
|
30
|
+
-webkit-border-radius: 3px;
|
31
|
+
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1), 0 1px 0 white;
|
32
|
+
-webkit-transition: all 0.2s;
|
33
|
+
padding: 4px;
|
34
|
+
width: 180px; }
|
35
|
+
#filter:focus {
|
36
|
+
outline: none;
|
37
|
+
background: #f4f4f4;
|
38
|
+
border: 1px solid #646464; }
|
39
|
+
|
40
|
+
.table-wrapper {
|
41
|
+
min-width: 700px; }
|
42
|
+
|
43
|
+
table {
|
44
|
+
border: 1px solid grey;
|
45
|
+
background: #e0dedb;
|
46
|
+
border-collapse: collapse;
|
47
|
+
width: 100%;
|
48
|
+
margin-bottom: 1em;
|
49
|
+
-webkit-box-shadow: 0 1px 0 white; }
|
50
|
+
|
51
|
+
table.source, pre, code {
|
52
|
+
font: 11px/1.2em Menlo; }
|
53
|
+
|
54
|
+
td pre {
|
55
|
+
margin: 0; }
|
56
|
+
|
57
|
+
.summary {
|
58
|
+
margin-bottom: 1em;
|
59
|
+
background: #e0dedb; }
|
60
|
+
.summary tbody .name, .summary tbody .name a {
|
61
|
+
color: black;
|
62
|
+
font-weight: bold; }
|
63
|
+
.summary tbody tr:hover {
|
64
|
+
background: #c8c5c0; }
|
65
|
+
.summary thead {
|
66
|
+
background: #333333;
|
67
|
+
color: #cccccc; }
|
68
|
+
.summary thead th {
|
69
|
+
cursor: pointer; }
|
70
|
+
.summary tr {
|
71
|
+
text-align: left; }
|
72
|
+
.summary th, .summary td {
|
73
|
+
padding: 0.5em; }
|
74
|
+
.summary .header::after {
|
75
|
+
font-size: 10px;
|
76
|
+
margin-left: 10px; }
|
77
|
+
.summary .descending::after {
|
78
|
+
content: "▼"; }
|
79
|
+
.summary .ascending::after {
|
80
|
+
content: "▲"; }
|
81
|
+
.summary .lines, .summary .loc, .summary .ran, .summary .cov, .summary .code {
|
82
|
+
width: 100px; }
|
83
|
+
|
84
|
+
.totals {
|
85
|
+
border-top: 1px solid grey;
|
86
|
+
background: #c8c5c0;
|
87
|
+
font-weight: bold; }
|
88
|
+
|
89
|
+
.source tr pre {
|
90
|
+
margin-left: 3px; }
|
91
|
+
.source tr .count {
|
92
|
+
background: white;
|
93
|
+
-webkit-border-radius: 4px;
|
94
|
+
-webkit-border-top-left-radius: 0px;
|
95
|
+
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
|
96
|
+
border: 1px solid black;
|
97
|
+
display: block;
|
98
|
+
padding: 3px;
|
99
|
+
position: absolute;
|
100
|
+
margin-top: -1.3em;
|
101
|
+
right: 15px;
|
102
|
+
opacity: 0; }
|
103
|
+
.source tr .no {
|
104
|
+
color: #cccccc;
|
105
|
+
background: #333333;
|
106
|
+
padding: 0 0 0 3px;
|
107
|
+
width: 25px; }
|
108
|
+
.source tr:hover .count {
|
109
|
+
opacity: 1; }
|
110
|
+
.source tr:hover .no {
|
111
|
+
color: white; }
|
112
|
+
.source tr.excluded {
|
113
|
+
background: #e0dedb; }
|
114
|
+
.source tr.excluded:hover {
|
115
|
+
background: #c8c5c0; }
|
116
|
+
.source tr.unran {
|
117
|
+
background: #ce8b8c; }
|
118
|
+
.source tr.unran:hover {
|
119
|
+
background: #bf6768; }
|
120
|
+
.source tr.ran {
|
121
|
+
background: #bed2be; }
|
122
|
+
.source tr.ran:hover {
|
123
|
+
background: #a0bda0; }
|
124
|
+
|
125
|
+
footer {
|
126
|
+
color: rgba(0, 0, 0, 0.6);
|
127
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); }
|
128
|
+
footer a {
|
129
|
+
color: black; }
|
data/templates/html/file.erb
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
<html lang="en">
|
3
3
|
<head>
|
4
4
|
<meta charset="utf-8" />
|
5
|
-
<title><%= file
|
6
|
-
<link rel="stylesheet" href="styles.css" type="text/css" />
|
7
|
-
<script type="text/javascript" src="jquery.js"></script>
|
8
|
-
<script type="text/javascript" src="main.js"></script>
|
9
|
-
<script type="text/javascript" src="plugins.js"></script>
|
5
|
+
<title><%= file.path %></title>
|
6
|
+
<link rel="stylesheet" href="<%= file.root %>styles.css" type="text/css" />
|
7
|
+
<script type="text/javascript" src="<%= file.root %>jquery.js"></script>
|
8
|
+
<script type="text/javascript" src="<%= file.root %>main.js"></script>
|
9
|
+
<script type="text/javascript" src="<%= file.root %>plugins.js"></script>
|
10
10
|
</head>
|
11
|
-
|
11
|
+
|
12
12
|
<body>
|
13
13
|
<header>
|
14
|
-
<h1><a href="index.html">Coverage</a></h1>
|
15
|
-
<h2><%= file
|
14
|
+
<h1><a href="<%= file.root %>index.html">Coverage</a></h1>
|
15
|
+
<h2><%= file.path %></h2>
|
16
16
|
</header>
|
17
|
-
|
17
|
+
|
18
18
|
<div class="table-wrapper">
|
19
19
|
<table class="summary" border="none">
|
20
20
|
<thead>
|
@@ -29,26 +29,26 @@
|
|
29
29
|
</thead>
|
30
30
|
<tbody>
|
31
31
|
<tr>
|
32
|
-
<td class="name"><%= file
|
33
|
-
<td><%=
|
34
|
-
<td><%=
|
35
|
-
<td><%=
|
36
|
-
<td><%= coverage
|
37
|
-
<td><%= coverage
|
32
|
+
<td class="name"><%= file.path %></td>
|
33
|
+
<td><%= lines.total %></td>
|
34
|
+
<td><%= lines.code %></td>
|
35
|
+
<td><%= lines.ran %></td>
|
36
|
+
<td><%= coverage.total %></td>
|
37
|
+
<td><%= coverage.code %></td>
|
38
38
|
</tr>
|
39
39
|
</tbody>
|
40
40
|
</table>
|
41
41
|
</div>
|
42
|
-
|
42
|
+
|
43
43
|
<div class="table-wrapper">
|
44
44
|
<table class="source" border="none">
|
45
|
-
<% file
|
45
|
+
<% file.source.zip(coverage.lines).each_with_index do |(line, count), i| %>
|
46
46
|
<% if count.nil? %>
|
47
47
|
<tr class="excluded">
|
48
48
|
<td class="no"><%= i %></td>
|
49
49
|
<td><pre><code><%= line %></code></pre></td>
|
50
50
|
</tr>
|
51
|
-
|
51
|
+
|
52
52
|
<% else %>
|
53
53
|
<tr class="<%= count.zero? ? "unran" : "ran" %>">
|
54
54
|
<td class="no"><%= i %></td>
|
@@ -58,14 +58,13 @@
|
|
58
58
|
<% end %>
|
59
59
|
</table>
|
60
60
|
</div>
|
61
|
-
|
62
|
-
|
61
|
+
|
62
|
+
|
63
63
|
<footer>
|
64
64
|
<span>
|
65
|
-
Generated at <%= time %> with
|
65
|
+
Generated at <%= time %> with
|
66
66
|
<a href="http://github.com/hawx/duvet"><%= name %> <%= version %></a>
|
67
67
|
</span>
|
68
68
|
</footer>
|
69
69
|
</body>
|
70
70
|
</html>
|
71
|
-
|