duvet 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module Duvet
2
- VERSION = '0.3.3'
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
@@ -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
@@ -7,13 +7,7 @@ Coverage.start
7
7
  require_relative '../lib/duvet'
8
8
  Duvet.start :filter => 'lib/duvet'
9
9
 
10
- require 'minitest/mock'
10
+ require 'minitest/autorun'
11
11
  require 'minitest/pride'
12
12
 
13
- require 'rr'
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; }
@@ -2,19 +2,19 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title><%= file['path'] %></title>
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['path'] %></h2>
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['path'] %></td>
33
- <td><%= file['lines'] %></td>
34
- <td><%= file['lines_code']%></td>
35
- <td><%= file['lines_ran']%></td>
36
- <td><%= coverage['total']%></td>
37
- <td><%= coverage['code']%></td>
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['source'].zip(coverage['lines']).each_with_index do |(line, count), i| %>
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
-