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,90 @@
1
+ module Lemon
2
+
3
+ # Test Instances are used to organize unit tests into groups, so as to address
4
+ # specific scenarios for a given class.
5
+ class TestContext
6
+
7
+ # The test case to which this concern belongs.
8
+ attr :testcase
9
+
10
+ # The description of this concern. Make this
11
+ # as detailed as you wish.
12
+ attr :description
13
+
14
+ # New case instance.
15
+ def initialize(testcase, description, options={}, &block)
16
+ @testcase = testcase
17
+ @description = description.to_s
18
+ @function = options[:function] || options[:singleton]
19
+ @type = options[:type] || :context
20
+ @block = block
21
+ end
22
+
23
+ #
24
+ def teardown=(procedure)
25
+ @teardown = procedure
26
+ end
27
+
28
+ # Teardown instance.
29
+ def teardown(scope=nil)
30
+ if scope
31
+ scope.instance_eval(&@teardown) if @teardown
32
+ else
33
+ @teardown
34
+ end
35
+ end
36
+
37
+ # Create instance.
38
+ def setup(scope)
39
+ if @block
40
+ ins = scope.instance_eval(&@block)
41
+ end
42
+ ins
43
+ end
44
+
45
+ def function? ; false ; end
46
+ alias_method :meta?, :function?
47
+
48
+ # Returns the description with newlines removed.
49
+ def to_s
50
+ description.gsub(/\n/, ' ')
51
+ end
52
+ end
53
+
54
+ ##
55
+ #class TestInstance < TestContext
56
+ #
57
+ # # Create instance.
58
+ # def setup(scope)
59
+ # if @block
60
+ # ins = scope.instance_eval(&@block)
61
+ # raise "target type mismatch" unless testcase.target === ins
62
+ # end
63
+ # ins
64
+ # end
65
+ #
66
+ #end
67
+
68
+ =begin
69
+ #
70
+ class TestSingleton < TestContext
71
+
72
+ # Create instance.
73
+ def setup(scope)
74
+ if @block
75
+ ins = scope.instance_eval(&@block)
76
+ raise "target type mismatch" unless testcase.target == ins
77
+ else
78
+ ins = @testcase.target
79
+ end
80
+ ins
81
+ end
82
+
83
+ def function? ; true ; end
84
+ alias_method :meta?, :function?
85
+
86
+ end
87
+ =end
88
+
89
+ end
90
+
@@ -0,0 +1,216 @@
1
+ require 'lemon/model/test_case'
2
+ require 'lemon/model/snapshot'
3
+ #require 'lemon/model/main'
4
+
5
+ module Lemon
6
+
7
+ # Current suite being defined. This is used
8
+ # to define a Suite object via the toplevel DSL.
9
+ def self.suite
10
+ $lemon_suite #@suite ||= Lemon::TestSuite.new([])
11
+ end
12
+
13
+ #
14
+ def self.suite=(suite)
15
+ $lemon_suite = suite
16
+ end
17
+
18
+ # Test Suites encapsulate a set of test cases.
19
+ #
20
+ class TestSuite
21
+
22
+ # Files from which the suite is loaded.
23
+ attr :files
24
+
25
+ # Test cases in this suite.
26
+ attr :testcases
27
+
28
+ # List of pre-test procedures that apply suite-wide.
29
+ attr :before
30
+
31
+ # List of post-test procedures that apply suite-wide.
32
+ attr :after
33
+
34
+ # A snapshot of the system before the suite is loaded.
35
+ # Only set if +cover+ option is true.
36
+ #attr :canonical
37
+
38
+ # List of files to be covered. This primarily serves
39
+ # as a means for allowing one test to load another
40
+ # and ensuring converage remains accurate.
41
+ #attr :subtest
42
+
43
+ #attr :current_file
44
+
45
+ #def coverage
46
+ # @final_coveage ||= @coverage - @canonical
47
+ #end
48
+
49
+ #
50
+ #attr :options
51
+
52
+ attr :dsl
53
+
54
+ #
55
+ def initialize(files, options={})
56
+ @files = files.flatten
57
+ @options = options
58
+
59
+ @testcases = []
60
+
61
+ @before = {}
62
+ @after = {}
63
+
64
+ #load_helpers
65
+
66
+ #if cover? or cover_all?
67
+ # @coverage = Snapshot.new
68
+ # @canonical = Snapshot.capture
69
+ #end
70
+
71
+ @dsl = DSL.new(self) #, files)
72
+
73
+ load_files
74
+ end
75
+
76
+ #
77
+ #class Scope < Module
78
+ # def initialize
79
+ # extend self
80
+ # end
81
+ #end
82
+
83
+ # Iterate through this suite's test cases.
84
+ def each(&block)
85
+ @testcases.each(&block)
86
+ end
87
+
88
+ #
89
+ def cover?
90
+ @options[:cover]
91
+ end
92
+
93
+ #
94
+ def cover_all?
95
+ @options[:cover_all]
96
+ end
97
+
98
+ # TODO: automatic helper loading ?
99
+ #def load_helpers(*files)
100
+ # helpers = []
101
+ # filelist.each do |file|
102
+ # dir = File.dirname(file)
103
+ # hlp = Dir[File.join(dir, '{test_,}helper.rb')]
104
+ # helpers.concat(hlp)
105
+ # end
106
+ #
107
+ # helpers.each do |hlp|
108
+ # require hlp
109
+ # end
110
+ #end
111
+
112
+ #
113
+ def load_files #(*files)
114
+ s = Lemon.suite || self
115
+ Lemon.suite = self
116
+
117
+ filelist.each do |file|
118
+ #load_file(file)
119
+ load file #require file
120
+ end
121
+
122
+ Lemon.suite = s
123
+
124
+ #if cover?
125
+ # $stdout << "\n"
126
+ # $stdout.flush
127
+ #end
128
+
129
+ self #return Lemon.suite
130
+ end
131
+
132
+ #
133
+ #def load_file(file)
134
+ # #@current_file = file
135
+ # #if cover_all?
136
+ # # Covers(file)
137
+ # #else
138
+ # file = File.expand_path(file)
139
+ # @dsl.module_eval(File.read(file), file)
140
+ # #require(file) #load(file)
141
+ # #end
142
+ #end
143
+
144
+ # Directories glob *.rb files.
145
+ def filelist
146
+ @filelist ||= (
147
+ files = @files
148
+ files = files.map{ |f| Dir[f] }.flatten
149
+ files = files.map do |file|
150
+ if File.directory?(file)
151
+ Dir[File.join(file, '**', '*.rb')]
152
+ else
153
+ file
154
+ end
155
+ end.flatten
156
+ #files = files.map{ |f| File.expand_path(f) }
157
+ files.uniq
158
+ )
159
+ end
160
+
161
+ class DSL < Module
162
+ #
163
+ def initialize(test_suite)
164
+ @test_suite = test_suite
165
+ #module_eval(&code)
166
+ end
167
+
168
+ # TODO: need require_find() to avoid first snapshot ?
169
+ def covers(file)
170
+ #if @test_suite.cover?
171
+ # #return if $".include?(file)
172
+ # s = Snapshot.capture
173
+ # if require(file)
174
+ # z = Snapshot.capture
175
+ # @test_suite.coverage << (z - s)
176
+ # end
177
+ #else
178
+ require file
179
+ #end
180
+ end
181
+ alias_method :Covers, :covers
182
+
183
+ # Define a test case belonging to this suite.
184
+ def testcase(target_class, &block)
185
+ raise "lemon: case target must be a class or module" unless Module === target_class
186
+ @test_suite.testcases << TestCase.new(@test_suite, target_class, &block)
187
+ end
188
+
189
+ #
190
+ alias_method :TestCase, :testcase
191
+ alias_method :tests, :testcase
192
+
193
+ # Define a pre-test procedure to apply suite-wide.
194
+ def before(*matches, &block)
195
+ @test_suite.before[matches] = block #<< Advice.new(match, &block)
196
+ end
197
+ alias_method :Before, :before
198
+
199
+ # Define a post-test procedure to apply suite-wide.
200
+ def after(*matches, &block)
201
+ @test_suite.after[matches] = block #<< Advice.new(match, &block)
202
+ end
203
+ alias_method :After, :after
204
+
205
+ # Includes at the suite level are routed to the toplevel.
206
+ #def include(*mods)
207
+ # TOPLEVEL_BINDING.eval('self').instance_eval do
208
+ # include(*mods)
209
+ # end
210
+ #end
211
+
212
+ end
213
+
214
+ end
215
+
216
+ end
@@ -1,54 +1,58 @@
1
- module Lemon::Test
1
+ module Lemon
2
2
 
3
3
  #
4
- class Unit
4
+ class TestUnit
5
5
 
6
6
  # The test case to which this unit test belongs.
7
7
  attr :testcase
8
8
 
9
- # The concern which this test helps ensure.
10
- attr :concern
9
+ # The context to use for this test.
10
+ attr :context
11
11
 
12
12
  # A test unit +target+ is a method.
13
13
  attr :target
14
14
 
15
- # The aspect of the concern this test fulfills.
15
+ # The aspect of the instance this test fulfills.
16
16
  attr :aspect
17
17
 
18
18
  # Test procedure, in which test assertions should be made.
19
19
  attr :procedure
20
20
 
21
21
  # New unit test.
22
- def initialize(concern, target, options={}, &procedure)
23
- concern.assign(self)
24
-
25
- @concern = concern
26
- @testcase = concern.testcase
27
-
22
+ def initialize(testcase, target, options={}, &procedure)
23
+ @testcase = testcase
28
24
  @target = target
29
25
 
30
26
  @aspect = options[:aspect]
31
- @meta = options[:metaclass]
27
+ @function = options[:function] || options[:metaclass]
28
+ @context = options[:context]
29
+ @omit = options[:omit]
32
30
 
33
31
  @procedure = procedure
32
+
33
+ @tested = false
34
34
  end
35
35
 
36
- # Is this unit test for a meta-method?
37
- def meta?
38
- @meta
36
+ #
37
+ attr_accessor :omit
38
+
39
+ #
40
+ def name ; @target ; end
41
+
42
+ # Is this unit test for a class or module level method?
43
+ def function?
44
+ @function
39
45
  end
46
+ alias_method :meta?, :function?
40
47
 
41
- # This method has the other end of the BIG FAT HACK. See Suite#const_missing.
42
- def call
43
- raise Pending unless procedure
44
- begin
45
- Lemon.test_stack << self # hack
46
- procedure.call
47
- ensure
48
- Lemon.test_stack.pop
49
- end
48
+ #
49
+ def omit?
50
+ @omit
50
51
  end
51
52
 
53
+ #
54
+ attr_accessor :tested
55
+
52
56
  # The suite to which this unit test belongs.
53
57
  def suite
54
58
  testcase.suite
@@ -74,9 +78,19 @@ module Lemon::Test
74
78
  #
75
79
  def to_s
76
80
  if meta?
77
- "#{testcase}.#{target} #{aspect}"
81
+ "#{testcase}.#{target}"
78
82
  else
79
- "#{testcase}##{target} #{aspect}"
83
+ "#{testcase}##{target}"
84
+ end
85
+ end
86
+
87
+ #
88
+ def description
89
+ if meta?
90
+ "#{testcase} #{instance} .#{target} #{aspect}"
91
+ else
92
+ a = /^[aeiou]/i =~ testcase.to_s ? 'An' : 'A'
93
+ "#{a} #{testcase} #{instance} receiving ##{target} #{aspect}"
80
94
  end
81
95
  end
82
96
 
@@ -88,5 +102,3 @@ module Lemon::Test
88
102
 
89
103
  end
90
104
 
91
-
92
-
@@ -1,5 +1,4 @@
1
- module Lemon
2
- module CoverSheet
1
+ module Lemon::CoverReports
3
2
 
4
3
  class Abstract
5
4
 
@@ -21,40 +20,40 @@ module CoverSheet
21
20
  #
22
21
  attr :coverage
23
22
 
24
- def uncovered_cases
25
- coverage.uncovered_cases
23
+ #
24
+ def render
25
+ end
26
+
27
+ def covered_units
28
+ coverage.covered
26
29
  end
27
30
 
28
31
  def uncovered_units
29
- coverage.uncovered_units
32
+ coverage.uncovered
30
33
  end
31
34
 
32
35
  def undefined_units
33
- coverage.undefined_units
36
+ coverage.undefined
34
37
  end
35
38
 
36
- #
37
- def red(string)
38
- @ansicolor ? ANSI::Code.red{ string } : string
39
+ def uncovered_cases
40
+ coverage.uncovered_cases
39
41
  end
40
42
 
41
43
  #
42
- def yellow(string)
43
- @ansicolor ? ANSI::Code.yellow{ string } : string
44
- end
44
+ def tally
45
+ c = covered_units.size
46
+ u = uncovered_units.size
47
+ t = c + u
45
48
 
46
- #
47
- def green(string)
48
- @ansicolor ? ANSI::Code.green{ string } : string
49
- end
49
+ pc = c * 100 / t
50
+ pu = u * 100 / t
50
51
 
51
- #
52
- def tally
53
- "#{uncovered_cases.size} uncovered cases, #{uncovered_units.size} uncovered units, #{undefined_units.size} undefined units"
52
+ "#{pc}% #{c}/#{t} covered, #{pu}% #{u}/#{t} uncovered" +
53
+ " (#{undefined_units.size} undefined units, #{uncovered_cases.size} uncovered cases)"
54
54
  end
55
55
 
56
56
  end
57
57
 
58
58
  end
59
- end
60
59