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
data/meta/data.rb ADDED
@@ -0,0 +1,29 @@
1
+ Object.__send__(:remove_const, :VERSION) if Object.const_defined?(:VERSION) # becuase Ruby 1.8~ gets in the way
2
+
3
+ module Lemon
4
+
5
+ def self.__DIR__
6
+ File.dirname(__FILE__)
7
+ end
8
+
9
+ def self.gemfile
10
+ @gemfile ||= (
11
+ require 'yaml'
12
+ YAML.load(File.new(__DIR__ + '/gemfile'))
13
+ )
14
+ end
15
+
16
+ def self.profile
17
+ @profile ||= (
18
+ require 'yaml'
19
+ YAML.load(File.new(__DIR__ + '/profile'))
20
+ )
21
+ end
22
+
23
+ def self.const_missing(name)
24
+ key = name.to_s.downcase
25
+ gemfile[key] || profile[key] || super(name)
26
+ end
27
+
28
+ end
29
+
data/meta/gemfile ADDED
@@ -0,0 +1,24 @@
1
+ ---
2
+ name : lemon
3
+ version : 0.8.2
4
+ date : 2010-09-05
5
+
6
+ requires:
7
+ - name: ae
8
+ group: runtime
9
+
10
+ - name: syckle
11
+ group: development
12
+
13
+ - name: box
14
+ group: development
15
+
16
+ - name: cucumber
17
+ group: test
18
+
19
+ - name: ae
20
+ group: test
21
+
22
+ - name: aruba
23
+ group: test
24
+
data/meta/profile ADDED
@@ -0,0 +1,17 @@
1
+ ---
2
+ title : Lemon
3
+ suite : proutils
4
+ summary: Pucker-tight Unit Testing
5
+ authors: Thomas Sawyer
6
+ contact: trans <transfire@gmail.com>
7
+ license: Apache 2.0
8
+
9
+ description:
10
+ Lemon is a unit testing framework that tightly correlates
11
+ class to test case and method to test unit.
12
+
13
+ resources:
14
+ homepage: http://proutils.github.com/lemon
15
+ repository: git://github.com/proutils/lemon.git
16
+
17
+ copyright: Copyright 2009 Thomas Sawyer
@@ -0,0 +1,18 @@
1
+ require 'fileutils'
2
+
3
+ Before :demo do
4
+ FileUtils.rm_r('tmp')
5
+ end
6
+
7
+ When "Given an example script in '(((.*?)))' as follows" do |name, text|
8
+ name = File.join('tmp', name) if /^tmp/ !~ name
9
+ FileUtils.mkdir_p(File.dirname(name))
10
+ File.open(name, 'w'){ |w| w << text }
11
+ end
12
+
13
+ When "given a test case in '(((.*?)))' as follows" do |name, text|
14
+ name = File.join('tmp', name) if /^tmp/ !~ name
15
+ FileUtils.mkdir_p(File.dirname(name))
16
+ File.open(name, 'w'){ |w| w << text }
17
+ end
18
+
@@ -0,0 +1,136 @@
1
+ == Complete Coverage
2
+
3
+ === Complete Coverage of Public Interface
4
+
5
+ Given an example script in 'tmp/lib/example.rb' as follows:
6
+
7
+ class C1
8
+ def f1; "f1"; end
9
+ def f2; "f2"; end
10
+ def f3; "f3"; end
11
+ end
12
+
13
+ class C2
14
+ def g1; "g1"; end
15
+ protected
16
+ def g2; "g2"; end
17
+ private
18
+ def g3; "g3"; end
19
+ end
20
+
21
+ And given a test case in 'tmp/test/example_case.rb' as follows:
22
+
23
+ covers 'example.rb'
24
+
25
+ testcase C1 do
26
+ unit :f1 => "Returns a String" do
27
+ end
28
+ unit :f2 => "Returns a String" do
29
+ end
30
+ unit :f3 => "Returns a String" do
31
+ end
32
+ end
33
+
34
+ testcase C2 do
35
+ unit :g1 => "Returns a String" do
36
+ end
37
+ end
38
+
39
+ And we get the coverage information via CoverageAnalyer.
40
+
41
+ require 'lemon'
42
+
43
+ tests = ['tmp/test/example_case.rb']
44
+
45
+ coverage = Lemon::CoverageAnalyzer.new(tests, :loadpath=>'tmp/lib')
46
+
47
+ Then we should see that there are no uncovered units.
48
+
49
+ coverage.uncovered_units.assert == []
50
+
51
+ And there should be 4 covered units,
52
+
53
+ coverage.covered_units.size.assert == 4
54
+
55
+ one for each public class and method.
56
+
57
+ units = coverage.covered_units.map{ |u| u.to_s }
58
+
59
+ units.assert.include?('C1#f1')
60
+ units.assert.include?('C1#f2')
61
+ units.assert.include?('C1#f3')
62
+
63
+ units.assert.include?('C2#g1')
64
+
65
+ There should not be any coverage for private and protected methods.
66
+
67
+ units.refute.include?('C2#g2')
68
+ units.refute.include?('C2#g3')
69
+
70
+ In addition there should be no uncovered_cases or undefined_units.
71
+
72
+ coverage.undefined_units.assert = []
73
+ coverage.uncovered_cases.assert = []
74
+
75
+ === Including Private and Protected Methods
76
+
77
+ We will use the same example classes as above, but in this case we will
78
+ add coverage for private and protected methods as well, given a test case
79
+ in 'tmp/test/example_case.rb' as follows:
80
+
81
+ covers 'example.rb'
82
+
83
+ testcase C1 do
84
+ unit :f1 => "Returns a String" do
85
+ end
86
+ unit :f2 => "Returns a String" do
87
+ end
88
+ unit :f3 => "Returns a String" do
89
+ end
90
+ end
91
+
92
+ testcase C2 do
93
+ unit :g1 => "Returns a String" do
94
+ end
95
+ unit :g2 => "Returns a String" do
96
+ end
97
+ unit :g3 => "Returns a String" do
98
+ end
99
+ end
100
+
101
+ And we get the coverage information via CoverageAnalyer.
102
+
103
+ require 'lemon'
104
+
105
+ tests = ['tmp/test/example_case.rb']
106
+
107
+ coverage = Lemon::CoverageAnalyzer.new(tests, :loadpath=>'tmp/lib', :private=>true)
108
+
109
+ Notice the use of the +private+ option. This will add private and protected
110
+ methods to the coverage analysis.
111
+
112
+ Then we should see that there are no uncovered units.
113
+
114
+ coverage.uncovered_units.assert == []
115
+
116
+ And there should be 6 covered units,
117
+
118
+ coverage.covered_units.size.assert == 6
119
+
120
+ one for each class and method.
121
+
122
+ units = coverage.covered_units.map{ |u| u.to_s }
123
+
124
+ units.assert.include?('C1#f1')
125
+ units.assert.include?('C1#f2')
126
+ units.assert.include?('C1#f3')
127
+
128
+ units.assert.include?('C2#g1')
129
+ units.assert.include?('C2#g2')
130
+ units.assert.include?('C2#g3')
131
+
132
+ In addition there should be no uncovered cases or undefined units.
133
+
134
+ coverage.undefined_units.assert = []
135
+ coverage.uncovered_cases.assert = []
136
+
@@ -0,0 +1,61 @@
1
+ == Core Extension Coverage
2
+
3
+ === Kernel Extensions
4
+
5
+ Given an example script in 'tmp/lib/example.rb' as follows:
6
+
7
+ module Kernel
8
+ def f1; "f1"; end
9
+ def f2; "f2"; end
10
+ def f3; "f3"; end
11
+ end
12
+
13
+ And given a test case in 'tmp/test/example_case.rb' as follows:
14
+
15
+ covers 'example.rb'
16
+
17
+ tests Kernel do
18
+ unit :f1 do
19
+ fl.assert == "f1"
20
+ end
21
+ unit :f2 do
22
+ f2.assert == "f2"
23
+ end
24
+ end
25
+
26
+ And we get the coverage information via CoverageAnalyer.
27
+
28
+ require 'lemon'
29
+
30
+ tests = ['tmp/test/example_case.rb']
31
+
32
+ coverage = Lemon::CoverageAnalyzer.new(tests, :loadpath=>'tmp/lib')
33
+
34
+ Then we should see that there are two covered units, #f1 and #f2.
35
+
36
+ coverage.covered_units.size.assert == 2
37
+
38
+ units = coverage.covered_units.map{ |u| u.to_s }
39
+
40
+ units.assert.include?('Kernel#f1')
41
+ units.assert.include?('Kernel#f2')
42
+
43
+ units.refute.include?('Kernel#f3')
44
+
45
+ And we should see one unconvered unit, #f3.
46
+
47
+ coverage.uncovered_units.size.assert == 1
48
+
49
+ units = coverage.uncovered_units.map{ |u| u.to_s }
50
+
51
+ units.assert.include?('Kernel#f3')
52
+
53
+ There should be zero uncovered cases.
54
+
55
+ coverage.uncovered_cases == []
56
+
57
+ And zero undefined unit.
58
+
59
+ coverage.undefined_units == []
60
+
61
+
@@ -0,0 +1,97 @@
1
+ == Incomplete Coverage
2
+
3
+ === Incomplete Coverage of Public Interface
4
+
5
+ Given an example script in 'tmp/lib/example.rb' as follows:
6
+
7
+ class C1
8
+ def f1; "f1"; end
9
+ def f2; "f2"; end
10
+ def f3; "f3"; end
11
+ end
12
+
13
+ class C2
14
+ def g1; "g1"; end
15
+ protected
16
+ def g2; "g2"; end
17
+ private
18
+ def g3; "g3"; end
19
+ end
20
+
21
+ class C3
22
+ def h1; "h1"; end
23
+ end
24
+
25
+ And given a test case in 'tmp/test/example_case.rb' as follows:
26
+
27
+ covers 'example.rb'
28
+
29
+ testcase C1 do
30
+ unit :f1 => "Returns a String" do
31
+ end
32
+ unit :f2 => "Returns a String" do
33
+ end
34
+ end
35
+
36
+ testcase C2 do
37
+ unit :x1 => "Does not exist" do
38
+ end
39
+ end
40
+
41
+ And we get the coverage information via CoverageAnalyer.
42
+
43
+ require 'lemon'
44
+
45
+ tests = ['tmp/test/example_case.rb']
46
+
47
+ coverage = Lemon::CoverageAnalyzer.new(tests, :loadpath=>'tmp/lib')
48
+
49
+ Then we should see that there are 2 unconvered units, C1#f3 and C2#g1
50
+ because no testcase unit was defined for them and they are both public methods.
51
+
52
+ coverage.uncovered_units.size.assert == 2
53
+
54
+ units = coverage.uncovered_units.map{ |u| u.to_s }
55
+
56
+ units.assert.include?('C1#f3')
57
+ units.assert.include?('C2#g1')
58
+
59
+ You might expect that 'C3#h1' would be in the uncovered units list as well,
60
+ since it is a public method and no test unit covers it. However, there is
61
+ no test case for C3 at all, so Lemon takes that to mean that C3 is of
62
+ no interest.
63
+
64
+ units.refute.include?('C3#h1')
65
+
66
+ But C3 will be listed in the uncovered cases list.
67
+
68
+ coverage.uncovered_cases == [C3]
69
+
70
+ Note that uncovered case methods can be included in the uncovered units list
71
+ by setting the +zealous+ option, which we will demonstrate later.
72
+
73
+ There should still be 3 covered units, C1#f1, C1#f2 and C2#x1.
74
+
75
+ coverage.covered_units.size.assert == 3
76
+
77
+ units = coverage.covered_units.map{ |u| u.to_s }
78
+
79
+ units.assert.include?('C1#f1')
80
+ units.assert.include?('C1#f2')
81
+ units.assert.include?('C2#x1')
82
+
83
+ But we will not find any covered units for class C2.
84
+
85
+ units.refute.include?('C2#g1')
86
+ units.refute.include?('C2#g2')
87
+ units.refute.include?('C2#g3')
88
+
89
+ Notice also that we defined a unit for C2#x1, a method that does not exist.
90
+ So it should be listed in the undefined units list.
91
+
92
+ coverage.undefined_units.size.assert == 1
93
+
94
+ units = coverage.undefined_units.map{ |u| u.to_s }
95
+
96
+ units.assert.include?('C2#x1')
97
+
@@ -32,7 +32,7 @@ Feature: Coverage
32
32
  When I cd to "example"
33
33
  And I run "lemon -c -Ilib test/case_complete.rb"
34
34
  Then the stdout should contain "0 uncovered cases"
35
- And the stdout should contain "0 uncovered units"
35
+ And the stdout should contain "0/4 uncovered"
36
36
  And the stdout should contain "0 undefined units"
37
37
 
38
38
  Scenario: Incomplete Example Case
@@ -48,7 +48,7 @@ Feature: Coverage
48
48
  def q; "q"; end
49
49
  end
50
50
  """
51
- Given a file named "example/test/case_complete.rb" with:
51
+ Given a file named "example/test/case_incomplete.rb" with:
52
52
  """
53
53
  Covers 'example'
54
54
  TestCase X do
@@ -58,8 +58,8 @@ Feature: Coverage
58
58
  end
59
59
  """
60
60
  When I cd to "example"
61
- And I run "lemon -c -Ilib test/case_complete.rb"
61
+ And I run "lemon -c -Ilib test/case_incomplete.rb"
62
62
  Then the stdout should contain "1 uncovered cases"
63
- And the stdout should contain "1 uncovered units"
63
+ And the stdout should contain "1/4 uncovered"
64
64
  And the stdout should contain "1 undefined units"
65
65
 
@@ -1,8 +1,8 @@
1
1
  Feature: Coverage
2
2
  As a developer
3
3
  In order to improve test coverge
4
- I want to able to write unit tests that target methods
5
- And run those tests
4
+ I want to able to generate test scaffolding
5
+ And limit the scaffolding to test units not already covered
6
6
 
7
7
  Scenario: Complete Example Case
8
8
  Given a directory named "example"
File without changes
File without changes
File without changes
@@ -1,8 +1,21 @@
1
- Covers File.dirname(__FILE__) + '/example.rbx'
2
- TestCase X do
3
- Unit :a => "Returns a String" do
1
+ covers File.dirname(__FILE__) + '/example.rb'
2
+
3
+ testcase X do
4
+
5
+ unit :a => "Returns a String" do
4
6
  end
5
- Unit :b => "Returns a String" do
7
+
8
+ unit :b => "Returns a String" do
9
+ end
10
+
11
+ unit :c => "Returns a String" do
6
12
  end
13
+
7
14
  end
8
15
 
16
+ testrcase Y do
17
+
18
+ unit :q => "Returns a String" do
19
+ end
20
+
21
+ end