lemon 0.9.0 → 0.9.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 (118) hide show
  1. checksums.yaml +7 -0
  2. data/{HISTORY.rdoc → HISTORY.md} +42 -11
  3. data/LICENSE.txt +27 -0
  4. data/README.md +48 -34
  5. data/{spec/coverage/01_complete.rdoc → demo/coverage/01_complete.md} +3 -3
  6. data/{spec/coverage/02_incomplete.rdoc → demo/coverage/02_incomplete.md} +2 -2
  7. data/{spec/coverage/03_extensions.rdoc → demo/coverage/03_extensions.md} +2 -2
  8. data/lib/lemon/cli/base.rb +50 -20
  9. data/lib/lemon/cli/generate.rb +51 -16
  10. data/lib/lemon/cli/lemon.ascii +84 -0
  11. data/lib/lemon/cli/obrother.rb +35 -0
  12. data/lib/lemon/cli/scaffold.rb +116 -0
  13. data/lib/lemon/cli.rb +19 -8
  14. data/lib/lemon/core_ext/module.rb +9 -0
  15. data/lib/lemon/core_ext.rb +2 -2
  16. data/lib/lemon/coverage/analyzer.rb +76 -5
  17. data/lib/lemon/coverage/cover_unit.rb +38 -14
  18. data/lib/lemon/coverage/formats/verbose.rb +1 -1
  19. data/lib/lemon/coverage/generator.rb +196 -0
  20. data/lib/lemon/coverage/snapshot.rb +16 -16
  21. data/lib/lemon/coverage/source_parser.rb +103 -37
  22. data/lib/lemon/ignore_callers.rb +19 -0
  23. data/lib/lemon/test_case.rb +135 -26
  24. data/lib/lemon/test_class.rb +16 -3
  25. data/lib/lemon/test_class_method.rb +58 -0
  26. data/lib/lemon/test_method.rb +57 -68
  27. data/lib/lemon/test_module.rb +47 -44
  28. data/lib/lemon/test_proc.rb +28 -2
  29. data/lib/lemon/test_scope.rb +14 -0
  30. data/lib/lemon/test_setup.rb +1 -1
  31. data/lib/lemon/test_world.rb +7 -0
  32. data/lib/lemon.rb +1 -15
  33. metadata +71 -147
  34. data/.gemspec +0 -152
  35. data/.gitignore +0 -8
  36. data/.reap/digest +0 -678
  37. data/.reap/test.reap +0 -7
  38. data/.ruby +0 -49
  39. data/Assembly +0 -37
  40. data/COPYING.rdoc +0 -33
  41. data/MANIFEST +0 -55
  42. data/PROFILE +0 -30
  43. data/Rakefile +0 -23
  44. data/VERSION +0 -1
  45. data/lib/lemon/core_ext/omission.rb +0 -18
  46. data/lib/lemon/generator.rb +0 -149
  47. data/lib/lemon.yml +0 -49
  48. data/notes/2010-05-05-coverage.rdoc +0 -47
  49. data/notes/2010-05-06-files-not-classes.rdoc +0 -19
  50. data/notes/2010-07-11-acid-testing.rdoc +0 -52
  51. data/notes/2010-08-02-enforcing-the-unit.md +0 -68
  52. data/notes/2010-08-03-new-api.md +0 -37
  53. data/notes/2011-07-07-nailing-down-the-nomenclature.md +0 -6
  54. data/site/.rsync-filter +0 -8
  55. data/site/assets/images/cut-lemon.png +0 -0
  56. data/site/assets/images/forkme.png +0 -0
  57. data/site/assets/images/github-logo.png +0 -0
  58. data/site/assets/images/lemon.jpg +0 -0
  59. data/site/assets/images/lemon.svg +0 -39
  60. data/site/assets/images/lemons-are-good.png +0 -0
  61. data/site/assets/images/opensource.png +0 -0
  62. data/site/assets/images/ruby-logo.png +0 -0
  63. data/site/assets/images/skin.jpg +0 -0
  64. data/site/assets/images/skin1.jpg +0 -0
  65. data/site/assets/images/tap.png +0 -0
  66. data/site/assets/images/title.png +0 -0
  67. data/site/assets/styles/class.css +0 -6
  68. data/site/assets/styles/reset.css +0 -17
  69. data/site/assets/styles/site.css +0 -33
  70. data/site/index.html +0 -218
  71. data/try/.test +0 -8
  72. data/try/case_error.rb +0 -18
  73. data/try/case_fail.rb +0 -19
  74. data/try/case_pass.rb +0 -42
  75. data/try/case_pending.rb +0 -18
  76. data/try/case_singleton.rb +0 -18
  77. data/try/case_untested.rb +0 -14
  78. data/try/fixtures/calculator.rb +0 -15
  79. data/try/fixtures/example-use.rb +0 -5
  80. data/try/fixtures/example.rb +0 -20
  81. data/try/helpers/loadpath.rb +0 -1
  82. data/work/deprecated/command/abstract.rb +0 -29
  83. data/work/deprecated/command/coverage.rb +0 -115
  84. data/work/deprecated/command/generate.rb +0 -124
  85. data/work/deprecated/command/test.rb +0 -112
  86. data/work/deprecated/cucumber.yml +0 -3
  87. data/work/deprecated/features/coverage.feature +0 -65
  88. data/work/deprecated/features/generate.feature +0 -66
  89. data/work/deprecated/features/step_definitions/coverage_steps.rb +0 -1
  90. data/work/deprecated/features/support/aruba.rb +0 -1
  91. data/work/deprecated/features/test.feature +0 -67
  92. data/work/deprecated/model/dsl/advice.rb +0 -78
  93. data/work/deprecated/model/dsl/subject.rb +0 -40
  94. data/work/deprecated/model/main.rb +0 -87
  95. data/work/deprecated/model/test.rb +0 -54
  96. data/work/deprecated/model/test_base_dsl.rb +0 -88
  97. data/work/deprecated/model/test_clause.rb +0 -112
  98. data/work/deprecated/model/test_context.rb +0 -90
  99. data/work/deprecated/model/test_feature.rb +0 -128
  100. data/work/deprecated/model/test_scenario.rb +0 -137
  101. data/work/deprecated/model/test_suite.rb +0 -297
  102. data/work/deprecated/rake.rb +0 -103
  103. data/work/deprecated/test/case_coverage_analyzer.rb +0 -25
  104. data/work/deprecated/test/case_test_case_dsl.rb +0 -46
  105. data/work/deprecated/test/fixtures/case_complete.rb +0 -25
  106. data/work/deprecated/test/fixtures/case_inclusion.rb +0 -18
  107. data/work/deprecated/test/fixtures/case_incomplete.rb +0 -12
  108. data/work/deprecated/test/fixtures/example.rb +0 -13
  109. data/work/deprecated/test/fixtures/helper.rb +0 -13
  110. data/work/deprecated/test/runner +0 -2
  111. data/work/old-tests/case_example.rb +0 -15
  112. data/work/old-tests/feature_example.rb +0 -40
  113. data/work/reference/dsl2.rb +0 -140
  114. data/work/reference/dynamic_constant_lookup.rb +0 -76
  115. /data/bin/{lemonade → lemons} +0 -0
  116. /data/{work/deprecated/features/support → demo/applique}/ae.rb +0 -0
  117. /data/{spec → demo}/applique/fs.rb +0 -0
  118. /data/{spec → demo}/coverage/applique/lemon.rb +0 -0
@@ -1,87 +0,0 @@
1
- # NOTE: This code is not being used. It is here for the time being
2
- # on the outseide change that I decide to go back to a toplevel design.
3
-
4
- require 'lemon/model/test_suite'
5
-
6
- class << self
7
-
8
- #
9
- def Covers(script)
10
- Lemon.suite.dsl.covers(script)
11
- end
12
- alias :Coverage :Covers
13
-
14
- # Define a general test case.
15
- def Case(target, &block)
16
- Lemon.suite.dsl.test_case(target, &block)
17
- end
18
-
19
- # Define a class test.
20
- def Class(target_class, &block)
21
- Lemon.suite.dsl.test_class(target_class, &block)
22
- end
23
-
24
- # Define a module test.
25
- def Module(target_module, &block)
26
- Lemon.suite.dsl.test_module(target_module, &block)
27
- end
28
-
29
- # Define a test feature.
30
- def Feature(target, &block)
31
- Lemon.suite.dsl.test_feature(target, &block)
32
- end
33
-
34
- #
35
- #def Before(match=nil, &block)
36
- # Lemon.suite.Before(match, &block)
37
- #end
38
-
39
- #
40
- #def After(match=nil, &block)
41
- # Lemon.suite.After(match, &block)
42
- #end
43
-
44
- #
45
- #def Helper(script)
46
- # Lemon.suite.Helper(script)
47
- #end
48
- end
49
-
50
- =begin
51
- # FIXME: This is a BIG FAT HACK! For the life of me I cannot find
52
- # a way to resolve module constants included in the test cases.
53
- # Because of closure, the constant lookup goes through here, and not
54
- # the Case singleton class. So to work around we must note each test
55
- # before it is run, and reroute the missing constants.
56
- #
57
- # This sucks and it is not thread safe. If anyone know how to fix,
58
- # please let me know. See Unit#call for the other end of this hack.
59
- #
60
- def Object.const_missing(name)
61
- if unit = Lemon.test_stack.last
62
- begin
63
- (class << unit.test_case; self; end).const_get(name)
64
- rescue NameError
65
- super(name)
66
- end
67
- else
68
- super(name)
69
- end
70
- end
71
-
72
- #def Object.const_missing(name)
73
- # if unit = Lemon.test_stack.last
74
- # klass = (class << unit.test_case; self; end)
75
- # if klass.const_defined?(name)
76
- # return klass.const_get(name)
77
- # end
78
- # end
79
- # super(name)
80
- #end
81
-
82
- # Get current running test. Used for the BIG FAT HACK.
83
- def Lemon.test_stack
84
- @@test_stack ||= []
85
- end
86
- =end
87
-
@@ -1,54 +0,0 @@
1
- require 'lemon/model/test_suite'
2
-
3
- module Test
4
- extend self
5
-
6
- #
7
- def covers(script)
8
- Lemon.suite.dsl.covers(script)
9
- end
10
- alias :Covers :covers
11
-
12
- alias :coverage :covers
13
- alias :Coverage :covers
14
-
15
- # Define a general test case.
16
- def case(target, &block)
17
- Lemon.suite.dsl.test_case(target, &block)
18
- end
19
- alias :Case :case
20
-
21
- # Define a class test.
22
- def class(target_class, &block)
23
- Lemon.suite.dsl.test_class(target_class, &block)
24
- end
25
- alias :Class :class
26
-
27
- # Define a module test.
28
- def module(target_module, &block)
29
- Lemon.suite.dsl.test_module(target_module, &block)
30
- end
31
- alias :Module :module
32
-
33
- # Define a test feature.
34
- def feature(target, &block)
35
- Lemon.suite.dsl.test_feature(target, &block)
36
- end
37
- alias :Feature :feature
38
-
39
- #
40
- #def Before(match=nil, &block)
41
- # Lemon.suite.Before(match, &block)
42
- #end
43
-
44
- #
45
- #def After(match=nil, &block)
46
- # Lemon.suite.After(match, &block)
47
- #end
48
-
49
- #
50
- #def Helper(script)
51
- # Lemon.suite.Helper(script)
52
- #end
53
-
54
- end
@@ -1,88 +0,0 @@
1
- module Lemon
2
-
3
- # Base class for TestCase DSLs.
4
- class BaseDSL < Module
5
-
6
- #
7
- def initialize(context, &code)
8
- @context = context
9
- @subject = context.subject
10
-
11
- module_eval(&code)
12
- end
13
-
14
- #
15
- def context(description, &block)
16
- @context.tests << TestCase.new(@context, description, &block)
17
- end
18
-
19
- #
20
- def test(description, &procedure)
21
- test = TestProc.new(
22
- @context,
23
- :description => description,
24
- :subject => subject,
25
- &procedure
26
- )
27
- @context.tests << test
28
- test
29
- end
30
-
31
- # Omit a test or test case from being run.
32
- #
33
- # omit test "something or other" do
34
- # # ...
35
- # end
36
- #
37
- def omit(test_or_case)
38
- test_or_case.omit = true
39
- end
40
- alias_method :Omit, :omit
41
-
42
-
43
-
44
-
45
- # Load a helper script applicable to this test case. Unlike requiring
46
- # a helper script, the #helper method will eval the file's contents
47
- # directly into the test context (using instance_eval).
48
- #
49
- # @param [String] file
50
- # File to eval into test context.
51
- #
52
- # FIXME: This is at odds with loading helpers automatically. How
53
- # to handle?
54
- def helper(file)
55
- instance_eval(File.read(file), file)
56
- end
57
-
58
- alias_method :Helper, :helper
59
-
60
- #def include(*mods)
61
- # extend *mods
62
- #end
63
-
64
- #def pending(message=nil)
65
- # raise Pending.new(message)
66
- #end
67
-
68
-
69
- # Before All and After All advice are bad form.
70
- #
71
- # # Define a "before all" procedure.
72
- # def prepare(&procedure)
73
- # before(&procedure)
74
- # end
75
- #
76
- # alias_method :Prepare, :prepare
77
- #
78
- # # Define an "after all" procedure.
79
- # def cleanup(&procedure)
80
- # after(&procedure)
81
- # end
82
- #
83
- # alias_method :Cleanup, :cleanup
84
- #
85
-
86
- end
87
-
88
- end
@@ -1,112 +0,0 @@
1
- module Lemon
2
-
3
- #
4
- class TestClause
5
-
6
- # New unit test procedure.
7
- #
8
- def initialize(scenario, description, options={}) #, &procedure)
9
- @context = scenario
10
- @description = description
11
-
12
- @type = options[:type]
13
-
14
- #@subject = options[:subject]
15
- #@aspect = options[:aspect]
16
- #@omit = options[:omit]
17
-
18
- #@procedure = procedure
19
-
20
- @tested = false
21
- end
22
-
23
- attr :type
24
-
25
- public
26
-
27
- # The case to which this test belongs.
28
- attr :context
29
-
30
- # Setup and teardown procedures.
31
- #attr :subject
32
-
33
- #
34
- #def target
35
- # context.
36
- #end
37
-
38
- # Description of test.
39
- attr :description
40
-
41
- # Test procedure, in which test assertions should be made.
42
- #attr :procedure
43
-
44
- # The before and after advice from the context.
45
- #def advice
46
- # context.advice
47
- #end
48
-
49
- #
50
- #def name ; @target ; end
51
-
52
- # Is this unit test for a class or module level method?
53
- #def function?
54
- # context.function?
55
- #end
56
-
57
- #
58
- attr_accessor :omit
59
-
60
- #
61
- def omit?
62
- @omit
63
- end
64
-
65
- #
66
- #attr_accessor :tested
67
-
68
- #
69
- #def to_s
70
- # if function?
71
- # "#{test_case}.#{target}"
72
- # else
73
- # "#{test_case}##{target}"
74
- # end
75
- #end
76
-
77
- #
78
- def to_s
79
- "#{type.to_s.capitalize} #{description}"
80
- end
81
-
82
- #
83
- def subject
84
- end
85
-
86
- #
87
- def scope
88
- context.scope
89
- end
90
-
91
- #
92
- def to_proc
93
- lambda{ call }
94
- end
95
-
96
- #
97
- #def match?(match)
98
- # match == target || match === aspect
99
- #end
100
-
101
- #
102
- def call
103
- context.run(self) do
104
- #subject.run_setup(scope) if subject
105
- scope.instance_exec(*arguments, &procedure)
106
- #subject.run_teardown(scope) if subject
107
- end
108
- end
109
-
110
- end
111
-
112
- end
@@ -1,90 +0,0 @@
1
- =begin
2
- module Lemon
3
-
4
- #
5
- class TestContext
6
-
7
- # The test case to which this concern belongs.
8
- attr :test_case
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(test_case, description, options={}, &block)
16
- @test_case = test_case
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
- scope.instance_eval(&@block)
41
- end
42
- end
43
-
44
- def function? ; false ; end
45
- alias_method :meta?, :function?
46
-
47
- # Returns the description with newlines removed.
48
- def to_s
49
- description.gsub(/\n/, ' ')
50
- end
51
- end
52
-
53
- end
54
- =end
55
-
56
- =begin
57
- #
58
- class TestInstance < TestContext
59
-
60
- # Create instance.
61
- def setup(scope)
62
- if @block
63
- ins = scope.instance_eval(&@block)
64
- raise "target type mismatch" unless test_case.target === ins
65
- end
66
- ins
67
- end
68
-
69
- end
70
-
71
- #
72
- class TestSingleton < TestContext
73
-
74
- # Create instance.
75
- def setup(scope)
76
- if @block
77
- ins = scope.instance_eval(&@block)
78
- raise "target type mismatch" unless test_case.target == ins
79
- else
80
- ins = @test_case.target
81
- end
82
- ins
83
- end
84
-
85
- def function? ; true ; end
86
- alias_method :meta?, :function?
87
-
88
- end
89
- =end
90
-
@@ -1,128 +0,0 @@
1
- require 'lemon/model/pending'
2
- require 'lemon/model/test_context'
3
- require 'lemon/model/test_advice'
4
- require 'lemon/model/test_scenario'
5
-
6
- module Lemon
7
-
8
- # The TestFeature ...
9
- #
10
- # * `tests` are _scenarios_,
11
- # * `advice` are _given_, _when_ and _then_ rules.
12
- #
13
- class TestFeature < TestCase
14
-
15
- #
16
- def initialize(context, settings={}, &block)
17
- @story = []
18
- super(context, settings, &block)
19
- end
20
-
21
- ## This has to be redefined in each subclass to pick
22
- ## up there respective DSL classes.
23
- #def evaluate(&block)
24
- # @dsl = DSL.new(self, &block)
25
- #end
26
-
27
- attr :story
28
-
29
- # Feature scenarios are tests.
30
- alias_method :scenarios, :tests
31
-
32
- #
33
- def to_s
34
- "Feature #{target}"
35
- end
36
-
37
- #
38
- def to_s #description
39
- (["Feature: #{target}"] + story).join("\n ")
40
- end
41
-
42
- # Run test in the context of this case.
43
- #
44
- # @param [TestProc] test
45
- # The test procedure instance to run.
46
- #
47
- def run(&block)
48
- end
49
-
50
- #
51
- class DSL < Module
52
-
53
- #
54
- def initialize(feature, &code)
55
- @feature = feature
56
-
57
- module_eval(&code)
58
- end
59
-
60
- #
61
- def To(description)
62
- @feature.story << "To " + description
63
- end
64
-
65
- #
66
- def As(description)
67
- @feature.story << "As " + description
68
- end
69
-
70
- #
71
- def We(description)
72
- @feature.story << "We " + description
73
- end
74
-
75
- #
76
- def Scenario(description, &procedure)
77
- scenario = TestScenario.new(@feature, description, &procedure)
78
- @feature.scenarios << scenario
79
- scenario
80
- end
81
- alias_method :scenario, :Scenario
82
-
83
- # Omit a scenario from test runs.
84
- #
85
- # omit unit :foo do
86
- # # ...
87
- # end
88
- #
89
- def Omit(scenario)
90
- scenario.omit = true
91
- end
92
- alias_method :omit, :Omit
93
-
94
- # Given ...
95
- #
96
- # @param [String] description
97
- # A brief description of the _given_ criteria.
98
- #
99
- def Given(description, &procedure)
100
- @feature.advice[:given][description] = procedure
101
- end
102
- alias_method :given, :Given
103
-
104
- # When ...
105
- #
106
- # @param [String] description
107
- # A brief description of the _when_ criteria.
108
- #
109
- def When(description, &procedure)
110
- @feature.advice[:when][description] = procedure
111
- end
112
- alias_method :wence, :When
113
-
114
- # Then ...
115
- #
116
- # @param [String] description
117
- # A brief description of the _then_ criteria.
118
- #
119
- def Then(description, &procedure)
120
- @feature.advice[:then][description] = procedure
121
- end
122
- alias_method :hence, :Then
123
-
124
- end
125
-
126
- end
127
-
128
- end
@@ -1,137 +0,0 @@
1
- require 'lemon/model/test_clause'
2
-
3
- module Lemon
4
-
5
- #
6
- class TestScenario < TestCase
7
-
8
- #
9
- def initialize(feature, summary, options={}, &block)
10
- @feature = feature
11
- @summary = summary
12
-
13
- @tests = []
14
-
15
- evaluate(&block)
16
- end
17
-
18
- #
19
- def evaluate(&procedure)
20
- @dsl = DSL.new(self, &procedure)
21
- end
22
-
23
- #
24
- attr :feature
25
-
26
- #
27
- attr :dsl
28
-
29
- attr_accessor :omit
30
-
31
- #
32
- def omit?
33
- @omit
34
- end
35
-
36
- #
37
- def to_s
38
- "Scenario: #{@summary}"
39
- end
40
-
41
- def subject
42
-
43
- end
44
-
45
- #
46
- def run(clause)
47
- type = clause.type
48
- desc = clause.description
49
- feature.advice[type].each do |mask, proc|
50
- if md = match_regexp(mask).match(desc)
51
- scope.instance_exec(*md[1..-1], &proc)
52
- end
53
- end
54
- end
55
-
56
- #
57
- #--
58
- # TODO: Change so that the scope is the DSL
59
- # and includes the DSL of the context?
60
- #++
61
- def scope
62
- @scope ||= (
63
- #if feature
64
- # scope = feature.scope || Object.new
65
- # scope.extend(dsl)
66
- #else
67
- scope = Object.new
68
- scope.extend(dsl)
69
- #end
70
- )
71
- end
72
-
73
- #
74
- #def find
75
- # features.clauses[@type].find{ |c| c =~ @description }
76
- #end
77
-
78
- # Convert matching string into a regular expression. If the string
79
- # contains double parenthesis, such as ((.*?)), then the text within
80
- # them is treated as in regular expression and kept verbatium.
81
- #
82
- # TODO: Better way to isolate regexp. Maybe ?:(.*?) or /(.*?)/.
83
- #
84
- def match_regexp(str)
85
- str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
86
- x =~ /\A\(\((.*)\)\)\Z/ ? $1 : Regexp.escape(x)
87
- }.join
88
- str = str.gsub(/\\\s+/, '\s+')
89
- Regexp.new(str, Regexp::IGNORECASE)
90
- end
91
-
92
-
93
- # TODO: Need to ensure the correct order of Given, When, Then.
94
- class DSL < Module
95
-
96
- #
97
- def initialize(scenario, &code)
98
- @scenario = scenario
99
-
100
- module_eval(&code)
101
- end
102
-
103
- # Given ...
104
- #
105
- # @param [String] description
106
- # A brief description of what the setup procedure sets-up.
107
- #
108
- def Given(description)
109
- @scenario.tests << TestClause.new(@scenario, description, :type=>:given)
110
- end
111
- alias_method :given, :Given
112
-
113
- # When ...
114
- #
115
- # @param [String] description
116
- # A brief description of what the setup procedure sets-up.
117
- #
118
- def When(description)
119
- @scenario.tests << TestClause.new(@scenario, description, :type=>:when)
120
- end
121
- alias_method :wence, :When
122
-
123
- # Then ...
124
- #
125
- # @param [String] description
126
- # A brief description of what the setup procedure sets-up.
127
- #
128
- def Then(description)
129
- @scenario.tests << TestClause.new(@scenario, description, :type=>:then)
130
- end
131
- alias_method :hence, :Then
132
-
133
- end
134
-
135
- end
136
-
137
- end