lemon 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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