lemon 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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