lemon 0.8.5 → 0.9.0

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 (113) hide show
  1. data/{lemon.gemspec → .gemspec} +0 -0
  2. data/.ruby +4 -11
  3. data/Assembly +5 -11
  4. data/HISTORY.rdoc +31 -0
  5. data/MANIFEST +45 -55
  6. data/PROFILE +6 -6
  7. data/README.md +113 -0
  8. data/Rakefile +12 -3
  9. data/VERSION +1 -1
  10. data/bin/lemonade +8 -0
  11. data/lib/lemon.rb +52 -2
  12. data/lib/lemon.yml +4 -11
  13. data/lib/lemon/{model/ae.rb → ae.rb} +0 -0
  14. data/lib/lemon/cli.rb +28 -279
  15. data/lib/lemon/cli/base.rb +139 -0
  16. data/lib/lemon/cli/coverage.rb +52 -0
  17. data/lib/lemon/cli/generate.rb +51 -0
  18. data/lib/lemon/cli/test.rb +50 -0
  19. data/lib/lemon/core_ext.rb +7 -0
  20. data/lib/lemon/core_ext/kernel.rb +20 -0
  21. data/lib/lemon/core_ext/omission.rb +18 -0
  22. data/lib/lemon/{controller/coverage_analyzer.rb → coverage/analyzer.rb} +41 -19
  23. data/lib/lemon/{model → coverage}/cover_unit.rb +0 -0
  24. data/lib/lemon/{view/cover_reports → coverage/formats}/abstract.rb +0 -0
  25. data/lib/lemon/{view/cover_reports → coverage/formats}/compact.rb +1 -1
  26. data/lib/lemon/{view/cover_reports → coverage/formats}/outline.rb +1 -1
  27. data/lib/lemon/{view/cover_reports → coverage/formats}/verbose.rb +1 -1
  28. data/lib/lemon/{view/cover_reports → coverage/formats}/yaml.rb +1 -1
  29. data/lib/lemon/{model → coverage}/snapshot.rb +0 -0
  30. data/lib/lemon/{model → coverage}/source_parser.rb +0 -0
  31. data/lib/lemon/{controller/scaffold_generator.rb → generator.rb} +53 -14
  32. data/lib/lemon/test_advice.rb +63 -0
  33. data/lib/lemon/test_case.rb +270 -0
  34. data/lib/lemon/test_class.rb +28 -0
  35. data/lib/lemon/test_method.rb +207 -0
  36. data/lib/lemon/test_module.rb +114 -0
  37. data/lib/lemon/test_proc.rb +140 -0
  38. data/lib/lemon/test_setup.rb +54 -0
  39. data/lib/lemon/test_world.rb +9 -0
  40. data/notes/{2010-05-06-files_not_classes.rdoc → 2010-05-06-files-not-classes.rdoc} +0 -0
  41. data/notes/{2010-07-11-acid_testing.rdoc → 2010-07-11-acid-testing.rdoc} +0 -0
  42. data/notes/2011-07-07-nailing-down-the-nomenclature.md +6 -0
  43. data/site/index.html +7 -6
  44. data/{qed → spec}/applique/fs.rb +0 -0
  45. data/{qed → spec}/coverage/01_complete.rdoc +26 -16
  46. data/{qed → spec}/coverage/02_incomplete.rdoc +10 -7
  47. data/{qed → spec}/coverage/03_extensions.rdoc +10 -6
  48. data/spec/coverage/applique/lemon.rb +1 -0
  49. data/try/.test +8 -0
  50. data/try/case_error.rb +18 -0
  51. data/try/case_fail.rb +19 -0
  52. data/try/case_pass.rb +42 -0
  53. data/try/case_pending.rb +18 -0
  54. data/try/case_singleton.rb +18 -0
  55. data/try/case_untested.rb +14 -0
  56. data/try/fixtures/calculator.rb +15 -0
  57. data/{demo/fixture → try/fixtures}/example-use.rb +0 -0
  58. data/{demo/fixture → try/fixtures}/example.rb +0 -0
  59. data/try/helpers/loadpath.rb +1 -0
  60. data/{.config → work/deprecated}/cucumber.yml +0 -0
  61. data/{features → work/deprecated/features}/coverage.feature +0 -0
  62. data/{features → work/deprecated/features}/generate.feature +0 -0
  63. data/{features → work/deprecated/features}/step_definitions/coverage_steps.rb +0 -0
  64. data/{features → work/deprecated/features}/support/ae.rb +0 -0
  65. data/{features → work/deprecated/features}/support/aruba.rb +0 -0
  66. data/{features → work/deprecated/features}/test.feature +0 -0
  67. data/work/deprecated/model/dsl/advice.rb +78 -0
  68. data/work/deprecated/model/dsl/subject.rb +40 -0
  69. data/{lib/lemon → work/deprecated}/model/main.rb +40 -29
  70. data/work/deprecated/model/test.rb +54 -0
  71. data/work/deprecated/model/test_base_dsl.rb +88 -0
  72. data/work/deprecated/model/test_clause.rb +112 -0
  73. data/{lib/lemon → work/deprecated}/model/test_context.rb +24 -24
  74. data/work/deprecated/model/test_feature.rb +128 -0
  75. data/work/deprecated/model/test_scenario.rb +137 -0
  76. data/{lib/lemon → work/deprecated}/model/test_suite.rb +113 -32
  77. data/work/deprecated/rake.rb +103 -0
  78. data/{test → work/deprecated/test}/case_coverage_analyzer.rb +0 -0
  79. data/{test → work/deprecated/test}/case_test_case_dsl.rb +2 -2
  80. data/{test → work/deprecated/test}/fixtures/case_complete.rb +0 -0
  81. data/{test → work/deprecated/test}/fixtures/case_inclusion.rb +0 -0
  82. data/{test → work/deprecated/test}/fixtures/case_incomplete.rb +0 -0
  83. data/{test → work/deprecated/test}/fixtures/example.rb +0 -0
  84. data/{test → work/deprecated/test}/fixtures/helper.rb +0 -0
  85. data/{test → work/deprecated/test}/runner +0 -0
  86. data/work/old-tests/case_example.rb +15 -0
  87. data/work/old-tests/feature_example.rb +40 -0
  88. data/work/reference/dsl2.rb +4 -0
  89. metadata +101 -98
  90. data/README.rdoc +0 -103
  91. data/bin/lemon +0 -4
  92. data/demo/case_example_error.rb +0 -10
  93. data/demo/case_example_fail.rb +0 -15
  94. data/demo/case_example_pass.rb +0 -32
  95. data/demo/case_example_pending.rb +0 -14
  96. data/demo/case_example_untested.rb +0 -10
  97. data/lib/lemon/controller/test_runner.rb +0 -299
  98. data/lib/lemon/model/pending.rb +0 -10
  99. data/lib/lemon/model/test_case.rb +0 -305
  100. data/lib/lemon/model/test_unit.rb +0 -147
  101. data/lib/lemon/view/test_reports/abstract.rb +0 -256
  102. data/lib/lemon/view/test_reports/dotprogress.rb +0 -73
  103. data/lib/lemon/view/test_reports/html.rb +0 -146
  104. data/lib/lemon/view/test_reports/outline.rb +0 -118
  105. data/lib/lemon/view/test_reports/summary.rb +0 -131
  106. data/lib/lemon/view/test_reports/tap.rb +0 -49
  107. data/lib/lemon/view/test_reports/tapj.rb +0 -130
  108. data/lib/lemon/view/test_reports/tapy.rb +0 -141
  109. data/lib/lemon/view/test_reports/verbose.rb +0 -197
  110. data/work/sandbox/lib/sample.rb +0 -13
  111. data/work/sandbox/test/sample_case.rb +0 -12
  112. data/work/trash/example-cover.rb +0 -5
  113. data/work/trash/example.rb +0 -16
@@ -0,0 +1,88 @@
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
@@ -0,0 +1,112 @@
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,19 +1,19 @@
1
+ =begin
1
2
  module Lemon
2
3
 
3
- # Test Instances are used to organize unit tests into groups, so as to address
4
- # specific scenarios for a given class.
4
+ #
5
5
  class TestContext
6
6
 
7
7
  # The test case to which this concern belongs.
8
- attr :testcase
8
+ attr :test_case
9
9
 
10
10
  # The description of this concern. Make this
11
11
  # as detailed as you wish.
12
12
  attr :description
13
13
 
14
14
  # New case instance.
15
- def initialize(testcase, description, options={}, &block)
16
- @testcase = testcase
15
+ def initialize(test_case, description, options={}, &block)
16
+ @test_case = test_case
17
17
  @description = description.to_s
18
18
  @function = options[:function] || options[:singleton]
19
19
  @type = options[:type] || :context
@@ -37,9 +37,8 @@ module Lemon
37
37
  # Create instance.
38
38
  def setup(scope)
39
39
  if @block
40
- ins = scope.instance_eval(&@block)
40
+ scope.instance_eval(&@block)
41
41
  end
42
- ins
43
42
  end
44
43
 
45
44
  def function? ; false ; end
@@ -51,21 +50,24 @@ module Lemon
51
50
  end
52
51
  end
53
52
 
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
53
+ end
54
+ =end
67
55
 
68
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
+
69
71
  #
70
72
  class TestSingleton < TestContext
71
73
 
@@ -73,9 +75,9 @@ module Lemon
73
75
  def setup(scope)
74
76
  if @block
75
77
  ins = scope.instance_eval(&@block)
76
- raise "target type mismatch" unless testcase.target == ins
78
+ raise "target type mismatch" unless test_case.target == ins
77
79
  else
78
- ins = @testcase.target
80
+ ins = @test_case.target
79
81
  end
80
82
  ins
81
83
  end
@@ -86,5 +88,3 @@ module Lemon
86
88
  end
87
89
  =end
88
90
 
89
- end
90
-
@@ -0,0 +1,128 @@
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
@@ -0,0 +1,137 @@
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