lemon 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/.ruby +23 -14
  2. data/.yardopts +6 -0
  3. data/Config.rb +14 -0
  4. data/{HISTORY.rdoc → HISTORY.md} +26 -11
  5. data/LICENSE.txt +27 -0
  6. data/README.md +42 -28
  7. data/SPECSHEET.md +314 -0
  8. data/bin/{lemonade → lemons} +0 -0
  9. data/lib/lemon.yml +23 -14
  10. data/lib/lemon/cli.rb +19 -8
  11. data/lib/lemon/cli/base.rb +50 -20
  12. data/lib/lemon/cli/generate.rb +51 -16
  13. data/lib/lemon/cli/lemon.ascii +84 -0
  14. data/lib/lemon/cli/obrother.rb +35 -0
  15. data/lib/lemon/cli/scaffold.rb +116 -0
  16. data/lib/lemon/core_ext.rb +2 -2
  17. data/lib/lemon/core_ext/module.rb +9 -0
  18. data/lib/lemon/coverage/analyzer.rb +76 -5
  19. data/lib/lemon/coverage/cover_unit.rb +38 -14
  20. data/lib/lemon/coverage/formats/verbose.rb +1 -1
  21. data/lib/lemon/coverage/generator.rb +196 -0
  22. data/lib/lemon/coverage/snapshot.rb +16 -16
  23. data/lib/lemon/coverage/source_parser.rb +103 -37
  24. data/lib/lemon/ignore_callers.rb +19 -0
  25. data/lib/lemon/test_case.rb +135 -26
  26. data/lib/lemon/test_class.rb +16 -3
  27. data/lib/lemon/test_class_method.rb +58 -0
  28. data/lib/lemon/test_method.rb +57 -68
  29. data/lib/lemon/test_module.rb +47 -44
  30. data/lib/lemon/test_proc.rb +28 -2
  31. data/lib/lemon/test_scope.rb +14 -0
  32. data/lib/lemon/test_setup.rb +1 -1
  33. data/lib/lemon/test_world.rb +7 -0
  34. data/{work/deprecated/features/support → spec/applique}/ae.rb +0 -0
  35. data/spec/coverage/{01_complete.rdoc → 01_complete.md} +3 -3
  36. data/spec/coverage/{02_incomplete.rdoc → 02_incomplete.md} +2 -2
  37. data/spec/coverage/{03_extensions.rdoc → 03_extensions.md} +2 -2
  38. data/try/case_scope.rb +19 -0
  39. metadata +50 -102
  40. data/.gemspec +0 -152
  41. data/.gitignore +0 -8
  42. data/.reap/digest +0 -678
  43. data/.reap/test.reap +0 -7
  44. data/Assembly +0 -37
  45. data/COPYING.rdoc +0 -33
  46. data/MANIFEST +0 -55
  47. data/PROFILE +0 -30
  48. data/Rakefile +0 -23
  49. data/VERSION +0 -1
  50. data/lib/lemon/core_ext/omission.rb +0 -18
  51. data/lib/lemon/generator.rb +0 -149
  52. data/notes/2010-05-05-coverage.rdoc +0 -47
  53. data/notes/2010-05-06-files-not-classes.rdoc +0 -19
  54. data/notes/2010-07-11-acid-testing.rdoc +0 -52
  55. data/notes/2010-08-02-enforcing-the-unit.md +0 -68
  56. data/notes/2010-08-03-new-api.md +0 -37
  57. data/notes/2011-07-07-nailing-down-the-nomenclature.md +0 -6
  58. data/site/.rsync-filter +0 -8
  59. data/site/assets/images/cut-lemon.png +0 -0
  60. data/site/assets/images/forkme.png +0 -0
  61. data/site/assets/images/github-logo.png +0 -0
  62. data/site/assets/images/lemon.jpg +0 -0
  63. data/site/assets/images/lemon.svg +0 -39
  64. data/site/assets/images/lemons-are-good.png +0 -0
  65. data/site/assets/images/opensource.png +0 -0
  66. data/site/assets/images/ruby-logo.png +0 -0
  67. data/site/assets/images/skin.jpg +0 -0
  68. data/site/assets/images/skin1.jpg +0 -0
  69. data/site/assets/images/tap.png +0 -0
  70. data/site/assets/images/title.png +0 -0
  71. data/site/assets/styles/class.css +0 -6
  72. data/site/assets/styles/reset.css +0 -17
  73. data/site/assets/styles/site.css +0 -33
  74. data/site/index.html +0 -218
  75. data/work/deprecated/command/abstract.rb +0 -29
  76. data/work/deprecated/command/coverage.rb +0 -115
  77. data/work/deprecated/command/generate.rb +0 -124
  78. data/work/deprecated/command/test.rb +0 -112
  79. data/work/deprecated/cucumber.yml +0 -3
  80. data/work/deprecated/features/coverage.feature +0 -65
  81. data/work/deprecated/features/generate.feature +0 -66
  82. data/work/deprecated/features/step_definitions/coverage_steps.rb +0 -1
  83. data/work/deprecated/features/support/aruba.rb +0 -1
  84. data/work/deprecated/features/test.feature +0 -67
  85. data/work/deprecated/model/dsl/advice.rb +0 -78
  86. data/work/deprecated/model/dsl/subject.rb +0 -40
  87. data/work/deprecated/model/main.rb +0 -87
  88. data/work/deprecated/model/test.rb +0 -54
  89. data/work/deprecated/model/test_base_dsl.rb +0 -88
  90. data/work/deprecated/model/test_clause.rb +0 -112
  91. data/work/deprecated/model/test_context.rb +0 -90
  92. data/work/deprecated/model/test_feature.rb +0 -128
  93. data/work/deprecated/model/test_scenario.rb +0 -137
  94. data/work/deprecated/model/test_suite.rb +0 -297
  95. data/work/deprecated/rake.rb +0 -103
  96. data/work/deprecated/test/case_coverage_analyzer.rb +0 -25
  97. data/work/deprecated/test/case_test_case_dsl.rb +0 -46
  98. data/work/deprecated/test/fixtures/case_complete.rb +0 -25
  99. data/work/deprecated/test/fixtures/case_inclusion.rb +0 -18
  100. data/work/deprecated/test/fixtures/case_incomplete.rb +0 -12
  101. data/work/deprecated/test/fixtures/example.rb +0 -13
  102. data/work/deprecated/test/fixtures/helper.rb +0 -13
  103. data/work/deprecated/test/runner +0 -2
  104. data/work/old-tests/case_example.rb +0 -15
  105. data/work/old-tests/feature_example.rb +0 -40
  106. data/work/reference/dsl2.rb +0 -140
  107. data/work/reference/dynamic_constant_lookup.rb +0 -76
@@ -0,0 +1,116 @@
1
+ module Lemon
2
+
3
+ module CLI
4
+
5
+ require 'lemon/cli/generate'
6
+ require 'fileutils'
7
+
8
+ # Scaffold Command
9
+ class Scaffold < Generate
10
+
11
+ # TODO: To be on the safe side, maybe require a --force option in order
12
+ # to write into a test directory that already has content.
13
+
14
+ #
15
+ # Unlike the Generate command, the Scaffold commnad writes output
16
+ # to test files.
17
+ #
18
+ def generate_output(render_map)
19
+ render_map.each do |group, test|
20
+ file = test_file(group)
21
+
22
+ if File.exist?(file)
23
+ append_test(file, test)
24
+ else
25
+ write_test(file, test)
26
+ end
27
+ end
28
+ end
29
+
30
+ #
31
+ #
32
+ #
33
+ def command_parse(argv)
34
+ option_parser.banner = "Usage: lemons scaffold [options] [files ...]"
35
+ setup_options
36
+ option_parser.parse!(argv)
37
+ end
38
+
39
+ #
40
+ #
41
+ #
42
+ def setup_options
43
+ option_output
44
+ option_dryrun
45
+ super
46
+ end
47
+
48
+ #
49
+ # Output directory, default is `test`.
50
+ #
51
+ def output
52
+ options[:output] || 'test'
53
+ end
54
+
55
+ #
56
+ #
57
+ #
58
+ def dryrun?
59
+ options[:dryrun]
60
+ end
61
+
62
+ #
63
+ # Given the group name, convert it to a suitable test file name.
64
+ #
65
+ def test_file(group)
66
+ if options[:group] == :file
67
+ file = group
68
+ else
69
+ file = group.gsub('::', '/').downcase
70
+ end
71
+
72
+ dirname, basename = File.split(file)
73
+
74
+ if i = dirname.index('/')
75
+ dirname = dirname[i+1..-1]
76
+ file = File.join(dirname, output, "case_#{basename}")
77
+ else
78
+ file = File.join(output, "case_#{basename}")
79
+ end
80
+ end
81
+
82
+ #
83
+ # Write test file.
84
+ #
85
+ def write_test(file, test)
86
+ return if test.strip.empty?
87
+ if dryrun?
88
+ puts "[DRYRUN] write #{file}"
89
+ else
90
+ dir = File.dirname(file)
91
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
92
+ File.open(file, 'w'){ |f| f << test.to_s }
93
+ puts "write #{file}"
94
+ end
95
+ end
96
+
97
+ #
98
+ # Append tests to file.
99
+ #
100
+ def append_test(file, test)
101
+ return if test.strip.empty?
102
+ if dryrun?
103
+ puts "[DRYRUN] append #{file}"
104
+ else
105
+ dir = File.dirname(file)
106
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
107
+ File.open(file, 'a'){ |f| f << "\n" + test.to_s }
108
+ puts "append #{file}"
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -1,7 +1,7 @@
1
1
  if RUBY_VERSION > '1.9'
2
2
  require_relative 'core_ext/kernel'
3
- require_relative 'core_ext/omission'
3
+ require_relative 'core_ext/module'
4
4
  else
5
5
  require 'lemon/core_ext/kernel'
6
- require 'lemon/core_ext/omission'
6
+ require 'lemon/core_ext/module'
7
7
  end
@@ -0,0 +1,9 @@
1
+ class Module
2
+
3
+ #
4
+ def namespace
5
+ i = name.rindex('::')
6
+ i ? name[0...i] : name
7
+ end
8
+
9
+ end
@@ -24,6 +24,7 @@ module Lemon
24
24
  # @public = options[:public]
25
25
  #end
26
26
 
27
+ #
27
28
  # New Coverage object.
28
29
  #
29
30
  # CoverageAnalyzer.new(suite, :MyApp, :public => true)
@@ -63,7 +64,9 @@ module Lemon
63
64
  @suite = $TEST_SUITE.dup
64
65
  end
65
66
 
67
+ #
66
68
  # Load in prerequisites
69
+ #
67
70
  def initialize_prerequisites(options)
68
71
  loadpath = [options[:loadpath] || []].compact.flatten
69
72
  requires = [options[:requires] || []].compact.flatten
@@ -72,56 +75,80 @@ module Lemon
72
75
  requires.each{ |path| require(path) }
73
76
  end
74
77
 
78
+ #
79
+ #
75
80
  #
76
81
  def reset_suite
77
82
  $TEST_SUITE = []
78
83
  end
79
84
 
85
+ #
86
+ #
80
87
  #
81
88
  def suite
82
89
  @suite
83
90
  end
84
91
 
92
+ #
85
93
  # Paths of lemon tests and/or ruby scripts to be compared and covered.
86
94
  # This can include directories too, in which case all .rb scripts below
87
95
  # then directory will be included.
96
+ #
88
97
  attr :files
89
98
 
90
- ## Conical snapshot of system (before loading libraries to be covered).
91
- #attr :canonical
92
-
99
+ #
93
100
  # Report format.
101
+ #
94
102
  attr :format
95
103
 
104
+ #
105
+ #
96
106
  #
97
107
  attr :namespaces
98
108
 
109
+ #
110
+ ## Conical snapshot of system (before loading libraries to be covered).
111
+ #
112
+ #attr :canonical
113
+
114
+ #
115
+ #
99
116
  #
100
117
  def canonical
101
118
  @canonical #= Snapshot.capture
102
119
  end
103
120
 
121
+ #
122
+ #
104
123
  #
105
124
  def suite=(suite)
106
125
  raise ArgumentError unless TestSuite === suite
107
126
  @suite = suite
108
127
  end
109
128
 
129
+ #
110
130
  # Only use public methods for coverage.
131
+ #
111
132
  def public_only?
112
133
  !@private
113
134
  end
114
135
 
136
+ #
137
+ #
115
138
  #
116
139
  def private?
117
140
  @private
118
141
  end
119
142
 
143
+ #
120
144
  # Include methods of uncovered cases in uncovered units.
145
+ #
121
146
  def zealous?
122
147
  @zealous
123
148
  end
124
149
 
150
+ #
151
+ #
125
152
  #
126
153
  def namespaces
127
154
  @namespaces
@@ -138,6 +165,8 @@ module Lemon
138
165
  uncovered_cases # that should be all it takes
139
166
  end
140
167
 
168
+ #
169
+ #
141
170
  #
142
171
  def covered_units
143
172
  @covered_units ||= (
@@ -149,6 +178,8 @@ module Lemon
149
178
  )
150
179
  end
151
180
 
181
+ #
182
+ #
152
183
  #
153
184
  def covered_unit(test, list)
154
185
  case test
@@ -160,33 +191,43 @@ module Lemon
160
191
  list << Snapshot::Unit.new(
161
192
  test.context.target,
162
193
  test.target,
163
- :function=>test.function?
164
- )
194
+ :singleton=>test.class_method?
195
+ )
165
196
  else
166
197
  # ignore
167
198
  end
168
199
  end
169
200
 
201
+ #
202
+ #
170
203
  #
171
204
  def covered_namespaces
172
205
  @covered_namespaces ||= covered_units.map{ |u| u.namespace }.uniq
173
206
  end
174
207
 
208
+ #
209
+ #
175
210
  #
176
211
  def target_namespaces
177
212
  @target_namespaces ||= filter(covered_namespaces)
178
213
  end
179
214
 
215
+ #
180
216
  # Target system snapshot.
217
+ #
181
218
  def target
182
219
  @target ||= Snapshot.capture(target_namespaces)
183
220
  end
184
221
 
222
+ #
185
223
  # Current system snapshot.
224
+ #
186
225
  def current
187
226
  @current ||= Snapshot.capture
188
227
  end
189
228
 
229
+ #
230
+ #
190
231
  #
191
232
  def uncovered_units
192
233
  @uncovered_units ||= (
@@ -200,12 +241,16 @@ module Lemon
200
241
  )
201
242
  end
202
243
 
244
+ #
245
+ #
203
246
  #
204
247
  def undefined_units
205
248
  @undefined_units ||= covered_units - target.units
206
249
  end
207
250
 
251
+ #
208
252
  # List of modules/classes not covered.
253
+ #
209
254
  def uncovered_cases
210
255
  @uncovered_cases ||= (
211
256
  list = current.units - (target.units + canonical.units)
@@ -214,22 +259,30 @@ module Lemon
214
259
  )
215
260
  end
216
261
 
262
+ #
263
+ #
217
264
  #
218
265
  def uncovered_system
219
266
  @uncovered_system ||= Snapshot.capture(uncovered_cases)
220
267
  end
221
268
 
269
+ #
270
+ #
222
271
  #
223
272
  def canonical_cases
224
273
  @canonical_cases ||= canonical.units.map{ |u| u.namespace }.uniq
225
274
  end
226
275
 
276
+ #
277
+ #
227
278
  #
228
279
  alias_method :covered, :covered_units
229
280
  alias_method :uncovered, :uncovered_units
230
281
  alias_method :undefined, :undefined_units
231
282
 
283
+ #
232
284
  # Reset coverage data for recalcuation.
285
+ #
233
286
  def reset!
234
287
  @covered_units = nil
235
288
  @covered_namespaces = nil
@@ -240,12 +293,16 @@ module Lemon
240
293
  @current = nil
241
294
  end
242
295
 
296
+ #
243
297
  # Iterate over covered units.
298
+ #
244
299
  def each(&block)
245
300
  covered_units.each(&block)
246
301
  end
247
302
 
303
+ #
248
304
  # Number of covered units.
305
+ #
249
306
  def size
250
307
  covered_units.size
251
308
  end
@@ -289,6 +346,8 @@ module Lemon
289
346
 
290
347
  private
291
348
 
349
+ #
350
+ #
292
351
  #
293
352
  def system(*namespaces)
294
353
  namespaces = nil if namespaces.empty?
@@ -300,7 +359,9 @@ module Lemon
300
359
  # Snapshot.capture
301
360
  #end
302
361
 
362
+ #
303
363
  # Filter namespaces.
364
+ #
304
365
  def filter(ns)
305
366
  return ns if namespaces.nil? or namespaces.empty?
306
367
  #units = units.reject do |u|
@@ -311,6 +372,8 @@ module Lemon
311
372
  end
312
373
  end
313
374
 
375
+ #
376
+ #
314
377
  #
315
378
  def filter_units(units)
316
379
  return units if namespaces.nil? or namespaces.empty?
@@ -327,12 +390,16 @@ module Lemon
327
390
 
328
391
  public
329
392
 
393
+ #
394
+ #
330
395
  #
331
396
  def render
332
397
  reporter.render
333
398
  end
334
399
 
400
+ #
335
401
  # All output is handled by a reporter.
402
+ #
336
403
  def reporter
337
404
  @reporter ||= reporter_find(format)
338
405
  end
@@ -341,6 +408,8 @@ module Lemon
341
408
 
342
409
  DEFAULT_REPORTER = 'compact'
343
410
 
411
+ #
412
+ #
344
413
  #
345
414
  def reporter_find(format)
346
415
  format = format ? format.to_s.downcase : DEFAULT_REPORTER
@@ -353,6 +422,8 @@ module Lemon
353
422
  reporter.new(self)
354
423
  end
355
424
 
425
+ #
426
+ #
356
427
  #
357
428
  def reporter_list
358
429
  Dir[File.dirname(__FILE__) + '/formats/*.rb'].map do |rb|
@@ -5,45 +5,60 @@ module Lemon
5
5
  class CoverUnit
6
6
 
7
7
  attr :target
8
+
8
9
  attr :method
9
- attr :function
10
10
 
11
+ attr :singleton
12
+
13
+ #
11
14
  def initialize(target, method, props={})
12
- @target = target
13
- @method = method.to_sym
14
- @function = props[:function] ? true : false
15
- @covered = props[:covered]
15
+ @target = target
16
+ @method = method.to_sym
17
+ @covered = props[:covered]
18
+ @singleton = props[:singleton] ? true : false
16
19
 
17
- if @function
20
+ if @singleton
18
21
  @private = !@target.public_methods.find{ |m| m.to_sym == @method }
19
22
  else
20
23
  @private = !@target.public_instance_methods.find{ |m| m.to_sym == @method }
21
24
  end
22
25
  end
23
26
 
27
+ #
24
28
  # Method access is private or protected?
29
+ #
25
30
  def private?
26
31
  @private
27
32
  end
28
33
 
34
+ #
29
35
  # Marked as covered?
36
+ #
30
37
  def covered?
31
38
  @covered
32
39
  end
33
40
 
34
41
  #
35
- def function?
36
- @function
42
+ #
43
+ #
44
+ def singleton?
45
+ @singleton
37
46
  end
38
47
 
48
+ alias class_method? singleton?
49
+
50
+ #
51
+ #
39
52
  #
40
53
  def hash
41
- @target.hash ^ @method.hash ^ @function.hash
54
+ @target.hash ^ @method.hash ^ singleton.hash
42
55
  end
43
56
 
57
+ #
58
+ #
44
59
  #
45
60
  def to_s
46
- if @function
61
+ if singleton?
47
62
  "#{@target}.#{@method}"
48
63
  else
49
64
  "#{@target}##{@method}"
@@ -51,23 +66,32 @@ module Lemon
51
66
  end
52
67
  alias to_str to_s
53
68
 
69
+ #
70
+ #
71
+ #
54
72
  def eql?(other)
55
73
  return false unless Unit === other
56
74
  return false unless target == other.target
57
75
  return false unless method == other.method
58
- return false unless function == other.function
76
+ return false unless singleton == other.singleton
59
77
  return true
60
78
  end
61
79
 
80
+ #
81
+ #
82
+ #
62
83
  def inspect
63
- "#{target}#{function ? '.' : '#'}#{method}"
84
+ "#{target}#{singleton? ? '.' : '#'}#{method}"
64
85
  end
65
86
 
87
+ #
88
+ #
89
+ #
66
90
  def <=>(other)
67
91
  c = (target.name <=> other.target.name)
68
92
  return c unless c == 0
69
- return -1 if function && !other.function
70
- return 1 if !function && other.function
93
+ return -1 if singleton && !other.singleton
94
+ return 1 if !singleton && other.singleton
71
95
  method.to_s <=> other.method.to_s
72
96
  end
73
97
  end