lemon 0.8.1 → 0.8.2

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.
Files changed (79) hide show
  1. data/HISTORY.rdoc +15 -0
  2. data/README.rdoc +32 -14
  3. data/bin/lemon +3 -2
  4. data/demo/case_example_fail.rb +15 -0
  5. data/demo/case_example_pass.rb +32 -0
  6. data/demo/case_example_pending.rb +14 -0
  7. data/demo/case_example_untested.rb +10 -0
  8. data/demo/fixture/example-use.rb +5 -0
  9. data/demo/fixture/example.rb +20 -0
  10. data/lib/lemon.rb +2 -2
  11. data/lib/lemon/cli.rb +281 -0
  12. data/lib/lemon/controller/coverage_analyzer.rb +343 -0
  13. data/lib/lemon/controller/scaffold_generator.rb +110 -0
  14. data/lib/lemon/controller/test_runner.rb +284 -0
  15. data/lib/lemon/meta/data.rb +29 -0
  16. data/lib/lemon/meta/gemfile +24 -0
  17. data/{PROFILE → lib/lemon/meta/profile} +6 -5
  18. data/lib/lemon/model/ae.rb +4 -0
  19. data/lib/lemon/model/cover_unit.rb +75 -0
  20. data/lib/lemon/{dsl.rb → model/main.rb} +22 -28
  21. data/lib/lemon/model/pending.rb +10 -0
  22. data/lib/lemon/model/snapshot.rb +203 -0
  23. data/lib/lemon/model/source_parser.rb +198 -0
  24. data/lib/lemon/model/test_case.rb +221 -0
  25. data/lib/lemon/model/test_context.rb +90 -0
  26. data/lib/lemon/model/test_suite.rb +216 -0
  27. data/lib/lemon/{test/unit.rb → model/test_unit.rb} +40 -28
  28. data/lib/lemon/{coversheet → view/cover_reports}/abstract.rb +19 -20
  29. data/lib/lemon/view/cover_reports/compact.rb +37 -0
  30. data/lib/lemon/view/cover_reports/outline.rb +45 -0
  31. data/lib/lemon/view/cover_reports/verbose.rb +51 -0
  32. data/lib/lemon/view/cover_reports/yaml.rb +15 -0
  33. data/lib/lemon/view/test_reports/abstract.rb +149 -0
  34. data/lib/lemon/view/test_reports/dotprogress.rb +73 -0
  35. data/lib/lemon/view/test_reports/html.rb +146 -0
  36. data/lib/lemon/view/test_reports/outline.rb +118 -0
  37. data/lib/lemon/view/test_reports/summary.rb +131 -0
  38. data/lib/lemon/view/test_reports/tap.rb +49 -0
  39. data/lib/lemon/view/test_reports/verbose.rb +197 -0
  40. data/meta/data.rb +29 -0
  41. data/meta/gemfile +24 -0
  42. data/meta/profile +17 -0
  43. data/test/api/applique/fs.rb +18 -0
  44. data/test/api/coverage/complete.rdoc +136 -0
  45. data/test/api/coverage/extensions.rdoc +61 -0
  46. data/test/api/coverage/incomplete.rdoc +97 -0
  47. data/{features → test/cli}/coverage.feature +4 -4
  48. data/{features → test/cli}/generate.feature +2 -2
  49. data/{features → test/cli}/step_definitions/coverage_steps.rb +0 -0
  50. data/{features → test/cli}/support/ae.rb +0 -0
  51. data/{features → test/cli}/support/aruba.rb +0 -0
  52. data/{features → test/cli}/test.feature +0 -0
  53. data/test/fixtures/case_complete.rb +17 -4
  54. data/test/fixtures/case_inclusion.rb +18 -0
  55. data/test/fixtures/case_incomplete.rb +4 -4
  56. data/test/fixtures/example.rb +5 -0
  57. data/test/fixtures/helper.rb +13 -0
  58. data/test/runner +3 -0
  59. data/test/unit/case_coverage_analyzer.rb +25 -0
  60. data/test/unit/case_test_case_dsl.rb +46 -0
  61. metadata +87 -42
  62. data/REQUIRE +0 -9
  63. data/VERSION +0 -6
  64. data/lib/lemon/command.rb +0 -184
  65. data/lib/lemon/coverage.rb +0 -260
  66. data/lib/lemon/coversheet/outline.rb +0 -47
  67. data/lib/lemon/kernel.rb +0 -24
  68. data/lib/lemon/reporter.rb +0 -22
  69. data/lib/lemon/reporter/abstract.rb +0 -97
  70. data/lib/lemon/reporter/dotprogress.rb +0 -68
  71. data/lib/lemon/reporter/outline.rb +0 -105
  72. data/lib/lemon/reporter/verbose.rb +0 -143
  73. data/lib/lemon/runner.rb +0 -308
  74. data/lib/lemon/snapshot.rb +0 -185
  75. data/lib/lemon/test/case.rb +0 -139
  76. data/lib/lemon/test/concern.rb +0 -52
  77. data/lib/lemon/test/suite.rb +0 -229
  78. data/test/case_coverage.rb +0 -26
  79. data/test/case_testcase.rb +0 -58
@@ -0,0 +1,343 @@
1
+ require 'lemon/model/snapshot'
2
+ require 'lemon/model/main'
3
+
4
+ module Lemon
5
+
6
+ #
7
+ class CoverageAnalyzer
8
+
9
+ ## New Coverage object.
10
+ ##
11
+ ## Coverage.new('lib/', :MyApp, :public => true)
12
+ ##
13
+ #def initialize(suite_or_files, namespaces=nil, options={})
14
+ # @namespaces = namespaces || []
15
+ # case suite_or_files
16
+ # when Test::Suite
17
+ # @suite = suite_or_files
18
+ # @files = suite_or_files.files
19
+ # else
20
+ # @suite = Test::Suite.new(suite_or_files)
21
+ # @files = suite_or_files
22
+ # end
23
+ # #@canonical = @suite.canonical
24
+ # @public = options[:public]
25
+ #end
26
+
27
+ # New Coverage object.
28
+ #
29
+ # CoverageAnalyzer.new(suite, :MyApp, :public => true)
30
+ #
31
+ def initialize(files, options={})
32
+ @files = files
33
+
34
+ @namespaces = [options[:namespaces]].flatten.compact
35
+ @private = options[:private]
36
+ @format = options[:format]
37
+ @zealous = options[:zealous]
38
+
39
+ @reporter = reporter_find(@format)
40
+
41
+ initialize_prerequisites(options)
42
+
43
+ @canonical = Snapshot.capture #system #@suite.canonical
44
+
45
+ #@suite = Lemon.suite
46
+ @suite = Lemon::TestSuite.new(files, :cover=>true) #@suite = suite
47
+ Lemon.suite = @suite
48
+
49
+ files = files.map{ |f| Dir[f] }.flatten
50
+ files = files.map{ |f|
51
+ if File.directory?(f)
52
+ Dir[File.join(f, '**/*.rb')]
53
+ else
54
+ f
55
+ end
56
+ }.flatten.uniq
57
+ files = files.map{ |f| File.expand_path(f) }
58
+
59
+ files.each{ |s| load s } #require s }
60
+ end
61
+
62
+ # Load in prerequisites
63
+ def initialize_prerequisites(options)
64
+ loadpath = options[:loadpath] || []
65
+ requires = options[:requires] || []
66
+
67
+ loadpath.each{ |path| $LOAD_PATH.unshift(path) }
68
+ requires.each{ |path| require(path) }
69
+ end
70
+
71
+ #
72
+ attr :suite
73
+
74
+ # Paths of lemon tests and/or ruby scripts to be compared and covered.
75
+ # This can include directories too, in which case all .rb scripts below
76
+ # then directory will be included.
77
+ attr :files
78
+
79
+ ## Conical snapshot of system (before loading libraries to be covered).
80
+ #attr :canonical
81
+
82
+ # Report format.
83
+ attr :format
84
+
85
+ #
86
+ attr :namespaces
87
+
88
+ #
89
+ def canonical
90
+ @canonical #= Snapshot.capture
91
+ end
92
+
93
+ #
94
+ def suite=(suite)
95
+ raise ArgumentError unless TestSuite === suite
96
+ @suite = suite
97
+ end
98
+
99
+ # Only use public methods for coverage.
100
+ def public_only?
101
+ !@private
102
+ end
103
+
104
+ #
105
+ def private?
106
+ @private
107
+ end
108
+
109
+ # Include methods of uncovered cases in uncovered units.
110
+ def zealous?
111
+ @zealous
112
+ end
113
+
114
+ #
115
+ def namespaces
116
+ @namespaces
117
+ end
118
+
119
+ #
120
+ #def target_units
121
+ # @target_units ||= target_system.units
122
+ #end
123
+
124
+
125
+ # Trigger a full set of calculations.
126
+ def calculate
127
+ uncovered_cases # that should be all it takes
128
+ end
129
+
130
+ #
131
+ def covered_units
132
+ @covered_units ||= (
133
+ list = []
134
+ suite.each do |testcase|
135
+ testcase.testunits.each do |unit|
136
+ list << Snapshot::Unit.new(
137
+ unit.testcase.target,
138
+ unit.target,
139
+ :function=>unit.function?
140
+ )
141
+ end
142
+ end
143
+ list.uniq
144
+ )
145
+ end
146
+
147
+ #
148
+ def covered_namespaces
149
+ @covered_namespaces ||= covered_units.map{ |u| u.namespace }.uniq
150
+ end
151
+
152
+ #
153
+ def target_namespaces
154
+ @target_namespaces ||= filter(covered_namespaces)
155
+ end
156
+
157
+ # Target system snapshot.
158
+ def target
159
+ @target ||= Snapshot.capture(target_namespaces)
160
+ end
161
+
162
+ # Current system snapshot.
163
+ def current
164
+ @current ||= Snapshot.capture
165
+ end
166
+
167
+ #
168
+ def uncovered_units
169
+ @uncovered_units ||= (
170
+ units = target.units
171
+ if public_only?
172
+ units = units.select{ |u| u.public? }
173
+ end
174
+ units -= (covered_units + canonical.units)
175
+ units += uncovered_system.units if zealous?
176
+ units
177
+ )
178
+ end
179
+
180
+ #
181
+ def undefined_units
182
+ @undefined_units ||= covered_units - target.units
183
+ end
184
+
185
+ # List of modules/classes not covered.
186
+ def uncovered_cases
187
+ @uncovered_cases ||= (
188
+ list = current.units - (target.units + canonical.units)
189
+ list = list.map{ |u| u.namespace }.uniq
190
+ list - canonical_cases
191
+ )
192
+ end
193
+
194
+ #
195
+ def uncovered_system
196
+ @uncovered_system ||= Snapshot.capture(uncovered_cases)
197
+ end
198
+
199
+ #
200
+ def canonical_cases
201
+ @canonical_cases ||= canonical.units.map{ |u| u.namespace }.uniq
202
+ end
203
+
204
+ #
205
+ alias_method :covered, :covered_units
206
+ alias_method :uncovered, :uncovered_units
207
+ alias_method :undefined, :undefined_units
208
+
209
+ # Reset coverage data for recalcuation.
210
+ def reset!
211
+ @covered_units = nil
212
+ @covered_namespaces = nil
213
+ @target_namespaces = nil
214
+ @uncovered_units = nil
215
+ @undefined_units = nil
216
+ @target = nil
217
+ @current = nil
218
+ end
219
+
220
+ # Iterate over covered units.
221
+ def each(&block)
222
+ covered_units.each(&block)
223
+ end
224
+
225
+ # Number of covered units.
226
+ def size
227
+ covered_units.size
228
+ end
229
+
230
+ # Iterate over +paths+ and use #load to bring in all +.rb+ scripts.
231
+ #def load_system
232
+ # files = []
233
+ # paths.map do |path|
234
+ # if File.directory?(path)
235
+ # files.concat(Dir[File.join(path, '**', '*.rb')])
236
+ # else
237
+ # files.concat(Dir[path])
238
+ # end
239
+ # end
240
+ # files.each{ |file| load(file) }
241
+ #end
242
+
243
+ # # Snapshot of System to be covered. This takes a current snapshot
244
+ # # of the system and removes the canonical snapshot or filters out
245
+ # # everything but the selected namespace.
246
+ # def system
247
+ # if namespaces.empty?
248
+ # snapshot - canonical
249
+ # else
250
+ # (snapshot - canonical).filter do |ofmod|
251
+ # namespaces.any?{ |n| ofmod.name.start_with?(n.to_s) }
252
+ # end
253
+ # end
254
+ # end
255
+
256
+ #
257
+ #def system
258
+ # if namespaces.empty?
259
+ # suite.coverage
260
+ # else
261
+ # suite.coverage.filter do |ofmod|
262
+ # namespaces.any?{ |n| ofmod.name.start_with?(n.to_s) }
263
+ # end
264
+ # end
265
+ #end
266
+
267
+ private
268
+
269
+ #
270
+ def system(*namespaces)
271
+ namespaces = nil if namespaces.empty?
272
+ Snapshot.capture(namespaces)
273
+ end
274
+
275
+ # Get a snapshot of the system.
276
+ #def snapshot
277
+ # Snapshot.capture
278
+ #end
279
+
280
+ # Filter namespaces.
281
+ def filter(ns)
282
+ return ns if namespaces.nil? or namespaces.empty?
283
+ #units = units.reject do |u|
284
+ # /^Lemon::/ =~ u.namespace.to_s
285
+ #end
286
+ ns.select do |u|
287
+ namespaces.any?{ |ns| /^#{ns}(::|$)/ =~ u.namespace.to_s }
288
+ end
289
+ end
290
+
291
+ #
292
+ def filter_units(units)
293
+ return units if namespaces.nil? or namespaces.empty?
294
+ #units = units.reject do |u|
295
+ # /^Lemon::/ =~ u.namespace.to_s
296
+ #end
297
+ units = units.select do |u|
298
+ namespaces.any? do |ns|
299
+ /^#{ns}/ =~ u.namespace.to_s
300
+ end
301
+ end
302
+ units
303
+ end
304
+
305
+ public
306
+
307
+ #
308
+ def render
309
+ reporter.render
310
+ end
311
+
312
+ # All output is handled by a reporter.
313
+ def reporter
314
+ @reporter ||= reporter_find(format)
315
+ end
316
+
317
+ private
318
+
319
+ DEFAULT_REPORTER = 'compact'
320
+
321
+ #
322
+ def reporter_find(format)
323
+ format = format ? format.to_s.downcase : DEFAULT_REPORTER
324
+ format = reporter_list.find do |name|
325
+ /^#{format}/ =~ name
326
+ end
327
+ raise "unsupported format" unless format
328
+ require "lemon/view/cover_reports/#{format}"
329
+ reporter = Lemon::CoverReports.const_get(format.capitalize)
330
+ reporter.new(self)
331
+ end
332
+
333
+ #
334
+ def reporter_list
335
+ Dir[File.dirname(__FILE__) + '/../view/cover_reports/*.rb'].map do |rb|
336
+ File.basename(rb).chomp('.rb')
337
+ end
338
+ end
339
+
340
+ end#class Coverage
341
+
342
+ end#module Lemon
343
+
@@ -0,0 +1,110 @@
1
+ require 'lemon/controller/coverage_analyzer'
2
+
3
+ module Lemon
4
+
5
+ #
6
+ class ScaffoldGenerator
7
+
8
+ # New Scaffold Generator.
9
+ #
10
+ def initialize(files, options={})
11
+ @files = files
12
+
13
+ @coverage = CoverageAnalyzer.new(files, options)
14
+ @suite = @coverage.suite
15
+
16
+ @namespaces = options[:namespaces]
17
+ @private = options[:private]
18
+ @uncovered = options[:uncovered]
19
+ @all = options[:all]
20
+ end
21
+
22
+ # Returns CoverageAnalyzer instance.
23
+ def coverage
24
+ @coverage
25
+ end
26
+
27
+ #
28
+ def namespaces
29
+ @namespaces
30
+ end
31
+
32
+ #
33
+ def all?
34
+ @all
35
+ end
36
+
37
+ #
38
+ def covered?
39
+ @covered
40
+ end
41
+
42
+ # Include only uncovered methods.
43
+ def uncovered?
44
+ @uncovered
45
+ end
46
+
47
+ # Include private and protected methods.
48
+ def private?
49
+ @private
50
+ end
51
+
52
+ # Generate test template(s).
53
+ def generate
54
+ if all?
55
+ generate_all
56
+ elsif uncovered?
57
+ generate_uncovered
58
+ else
59
+ generate_target
60
+ end
61
+ end
62
+
63
+ #
64
+ def generate_target
65
+ render(filter(coverage.target.units))
66
+ end
67
+
68
+ #
69
+ def generate_uncovered
70
+ render(filter(coverage.uncovered))
71
+ end
72
+
73
+ # Generate code template.
74
+ def generate_all
75
+ render(Snapshot.capture(namespaces).units)
76
+ end
77
+
78
+ #
79
+ def filter(units)
80
+ return units if namespaces.nil? or namespaces.empty?
81
+ units.select do |u|
82
+ namespaces.any? do |ns|
83
+ /^#{ns}/ =~ u.namespace.to_s
84
+ end
85
+ end
86
+ end
87
+
88
+ # Generate code template.
89
+ def render(units)
90
+ code = []
91
+ mods = units.group_by{ |u| u.namespace }
92
+ mods.each do |mod, units|
93
+ code << "TestCase #{mod} do"
94
+ units.each do |unit|
95
+ next unless private? or unit.public?
96
+ if unit.function?
97
+ code << "\n MetaUnit :#{unit.method} => '' do\n\n end"
98
+ else
99
+ code << "\n Unit :#{unit.method} => '' do\n\n end"
100
+ end
101
+ end
102
+ code << "\nend\n"
103
+ end
104
+
105
+ code.join("\n")
106
+ end
107
+
108
+ end
109
+
110
+ end