lime 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby CHANGED
@@ -1,16 +1,15 @@
1
1
  ---
2
+ source:
3
+ - meta
2
4
  authors:
3
- - name: Thomas Sawyer
5
+ - name: Trans
4
6
  email: transfire@gmail.com
5
7
  copyrights:
6
- - holder: Thomas Sawyer
8
+ - holder: Rubyworks
7
9
  year: '2011'
8
10
  license: BSD-2-Clause
9
- replacements: []
10
- conflicts: []
11
11
  requirements:
12
- - name: test
13
- - name: ae
12
+ - name: rubytest
14
13
  - name: detroit
15
14
  groups:
16
15
  - build
@@ -23,7 +22,13 @@ requirements:
23
22
  groups:
24
23
  - test
25
24
  development: true
25
+ - name: ae
26
+ groups:
27
+ - test
28
+ development: true
26
29
  dependencies: []
30
+ alternatives: []
31
+ conflicts: []
27
32
  repositories:
28
33
  - uri: git://github.com/proutils/lime.git
29
34
  scm: git
@@ -31,18 +36,19 @@ repositories:
31
36
  resources:
32
37
  home: http://rubyworks.github.com/lime
33
38
  code: http://github.com/rubyworks/lime
34
- mail: http://groups.google.com/group/rubyworks-mailinglist
39
+ bugs: http://github.com/rubyworks/lime/issues
40
+ mail: http://groups.google.com/groups/rubyworks-mailinglist
41
+ extra: {}
35
42
  load_path:
36
43
  - lib
37
- extra:
38
- manifest: MANIFEST
39
- alternatives: []
40
44
  revision: 0
45
+ created: '2011-08-11'
46
+ summary: Pure Ruby Gherkin-style Test Framework
41
47
  title: Lime
42
- suite: RubyWorks
43
- summary: Gherkin-style Test Framework
44
- description: Lime is a pure Ruby variation of Cucumber's Gherkin BDD test system that
45
- runs on top of the Ruby Universal Test Harness.
46
- version: 0.2.0
48
+ version: 0.3.0
47
49
  name: lime
48
- date: '2011-08-11'
50
+ description: ! 'Lime is a pure Ruby variation of Cucumber''s Gherkin BDD test system
51
+
52
+ that runs on top of RubyTest, a Universal Test Harness for Ruby.'
53
+ organization: Rubyworks
54
+ date: '2012-03-03'
data/HISTORY.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Release History
2
2
 
3
+ ## 0.3.0 / 2012-03-03
4
+
5
+ Fix execution scope so that method definitions in Featurettes
6
+ are visible to advice procedures. Also will automatically require
7
+ any `*.rb` files in `featurettes` directory relative to feature
8
+ file.
9
+
10
+ Changes:
11
+
12
+ * Fix execution scope so that featurettes are included.
13
+ * Automatically require featurette files.
14
+ * Alias #I to #We.
15
+
3
16
 
4
17
  ## 0.2.0 / 2011-08-11
5
18
 
@@ -1,6 +1,8 @@
1
- BSD 2 Clause License
1
+ Lime, Pure-Ruby Gherkin-style BDD Test Framework
2
2
 
3
- Copyright 2011 Thomas Sawyer. All rights reserved.
3
+ Copyright 2011 Rubyworks. All rights reserved.
4
+
5
+ (BSD-2-Clause License)
4
6
 
5
7
  Redistribution and use in source and binary forms, with or without
6
8
  modification, are permitted provided that the following conditions are met:
data/README.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # Lime
2
2
 
3
- Author:: Thomas Sawyer
4
- License:: FreeBSD
5
- Copyright:: (c) 2011 Thomas Sawyer, Rubyworks
3
+ [Website](http://rubyworks.github.com/lime) /
4
+ [Source Code](http://github.com/rubyworks/lime) /
5
+ [Report Issue](http://github.com/rubyworks/lime/issues) /
6
+ [Mailing List](http://groups.google.com/groups/rubyworks-mailinglist)
6
7
 
7
8
 
8
9
  ## Description
9
10
 
10
- Lime is pure Ruby Gherkin-style test framework.
11
+ Lime is pure-Ruby Gherkin-style test framework.
11
12
 
12
13
 
13
- ## Example
14
+ ## Instruction
15
+
16
+ Lime lets you write features scripts using Ruby, yet still do
17
+ so with a close approximation to Gherkin domain language.
14
18
 
15
19
  ``` ruby
16
20
  Feature "Addition" do
@@ -54,12 +58,50 @@ Feature "Addition" do
54
58
  end
55
59
  ```
56
60
 
61
+ The last set of `Given` and `When` procedures are called the *advice definitions*. These
62
+ can be placed in their own modules and included into the Feature scope like any other module.
63
+ They simply need to include the `Lime::Featurette` module to do so. For instance:
64
+
65
+ ```ruby
66
+ module CalculatorAdvice
67
+ include Lime::Featurette
68
+
69
+ Given 'I have a calculator' do
70
+ require 'calculator'
71
+ @calculator = Calculator.new
72
+ end
73
+
74
+ Given 'I have entered (((\d+))) into the calculator' do |n|
75
+ @calculator.push n.to_i
76
+ end
77
+
78
+ When 'I press add' do
79
+ @result = @calculator.add
80
+ end
81
+
82
+ Then 'the result should be (((\d+))) on the screen' do |n|
83
+ @result.assert == n.to_i
84
+ end
85
+ end
86
+ ```
87
+
88
+ If you add such scripts to a subdirectory called `featurettes` relative to the
89
+ feature that uses them, then they will be loaded automatically when features
90
+ are run.
91
+
92
+ Speaking of which, to run features use the `rubytest` command line tool.
93
+
94
+ ```
95
+ $ rubytest -Ilib spec/feature_addition.rb
96
+ ```
97
+
98
+ See [RubyTest](http://rubyworks.github.com/rubytest) to learn more.
99
+
57
100
 
58
101
  ## Copyrights
59
102
 
60
- Copyright (c) 2011 Thomas Sawyer, Rubyworks
103
+ Copyright (c) 2011 Rubyworks
61
104
 
62
105
  Lime is distributed according to the terms of the *FreeBSD* license.
63
106
 
64
- See COPYING.rdoc for details.
65
-
107
+ See LICENSE.txt for details.
@@ -1,8 +1,8 @@
1
1
  # Ignore lime paths in backtraces
2
2
  ignore_path = File.expand_path(File.dirname(__FILE__) + '/lime')
3
3
  ignore_regexp = Regexp.new(Regexp.escape(ignore_path))
4
- RUBY_IGNORE_CALLERS = [] unless defined? RUBY_IGNORE_CALLERS
5
- RUBY_IGNORE_CALLERS << ignore_regexp
4
+ $RUBY_IGNORE_CALLERS ||= []
5
+ $RUBY_IGNORE_CALLERS << ignore_regexp
6
6
 
7
7
  # Make sure the global test array is defined.
8
8
  $TEST_SUITE ||= []
@@ -15,15 +15,33 @@ module Lime
15
15
  require 'lime/step'
16
16
 
17
17
  # Toplevel DSL.
18
+ #
18
19
  module DSL
19
20
 
21
+ #
20
22
  # Define a feature.
23
+ #
21
24
  def Feature(label, &block)
25
+ require_featurettes(File.dirname(caller[0]))
26
+
22
27
  $TEST_SUITE << Lime::Feature.new(:label=>label, &block)
23
28
  end
24
29
 
25
30
  alias :feature :Feature
26
31
 
32
+ #
33
+ # Require any featurettes located in `{feature_dir}/featurettes` directory.
34
+ #
35
+ def require_featurettes(feature_dir)
36
+ featurettes_dir = File.join(feature_dir, 'featurettes')
37
+ if File.directory?(featurettes_dir)
38
+ featurette_files = Dir[File.join(featurettes_dir, '*.rb')]
39
+ featurette_files.each do |file|
40
+ require file
41
+ end
42
+ end
43
+ end
44
+
27
45
  end
28
46
 
29
47
  end
@@ -4,6 +4,7 @@ module Lime
4
4
  require 'lime/world'
5
5
  require 'lime/advice'
6
6
  require 'lime/scenario'
7
+ require 'lime/featurette'
7
8
 
8
9
  # Features contain scenarios.
9
10
  #
@@ -38,8 +39,11 @@ module Lime
38
39
  @story = []
39
40
  @scenarios = []
40
41
 
41
- @scope = Scope.new(self)
42
- @scope.module_eval(&block)
42
+ @scope = Scope.new(self, &block)
43
+
44
+ @scenarios.each do |scenario|
45
+ scenario.scope.__send__(:extend, @scope)
46
+ end
43
47
  end
44
48
 
45
49
  # Convenience method for accessing advice, aka step definitions.
@@ -70,20 +74,22 @@ module Lime
70
74
 
71
75
  #
72
76
  def update(mixin)
73
- @advice[:given].concat mixin[:given] || []
74
- @advice[:when].concat mixin[:when] || []
75
- @advice[:then].concat mixin[:then] || []
76
- @scope.extend mixin if Module === mixin
77
+ @advice[:given].update( mixin[:given] || {} )
78
+ @advice[:when].update( mixin[:when] || {} )
79
+ @advice[:then].update( mixin[:then] || {} )
80
+
81
+ #@scope.__send__(:include, mixin) if Module === mixin
77
82
  end
78
83
 
79
84
  #
80
85
  class Scope < World
81
86
 
82
87
  #
83
- def initialize(feature) #, &code)
88
+ def initialize(feature, &block)
84
89
  @_feature = feature
85
90
  @_skip = false
86
- #module_eval(&code)
91
+
92
+ module_eval(&block) if block
87
93
  end
88
94
 
89
95
  #
@@ -107,6 +113,11 @@ module Lime
107
113
 
108
114
  alias :we :We
109
115
 
116
+ alias :I :We
117
+ alias :i :I
118
+
119
+ #
120
+ # Define a Scenario.
110
121
  #
111
122
  def Scenario(label, &procedure)
112
123
  scenario = Scenario.new(
@@ -167,86 +178,22 @@ module Lime
167
178
  @_skip = reason
168
179
  end
169
180
 
170
- # Is this necessary?
181
+ #
182
+ # Access to underlying feature instance.
183
+ #
171
184
  def _feature
172
185
  @_feature
173
186
  end
174
187
 
188
+ #
189
+ # Include module and if a Featurette, also update Feature instance.
175
190
  #
176
191
  def include(mixin)
177
- if Featurable === mixin
192
+ if Featurette === mixin
178
193
  @_feature.update(mixin)
179
- super(mixin)
180
- else
181
- super(mixin)
182
194
  end
195
+ super(mixin)
183
196
  end
184
-
185
- end
186
-
187
- # Convenience method for creating a feature mixin.
188
- #
189
- # @example
190
- #
191
- # module MyStepDefinitions
192
- # include Lime::Featurette
193
- #
194
- # Given "customer's name is '(((\s+)))'" do |name|
195
- # @name = name
196
- # end
197
- # end
198
- #
199
- # Feature do
200
- # include MyStepDefinitions
201
- # end
202
- #
203
- module Featurette
204
-
205
- def self.append_features(base)
206
- base.extend(self)
207
- base.module_eval %{
208
- @_advice = Hash.new{ |h,k| h[k]={} }
209
- }
210
- end
211
-
212
- # Given ...
213
- #
214
- # @param [String] description
215
- # A brief description of the _given_ criteria.
216
- #
217
- def Given(description, &procedure)
218
- @_advice[:given][description] = procedure
219
- end
220
-
221
- alias :given :Given
222
-
223
- # When ...
224
- #
225
- # @param [String] description
226
- # A brief description of the _when_ criteria.
227
- #
228
- def When(description, &procedure)
229
- @_advice[:when][description] = procedure
230
- end
231
-
232
- alias :wence :When
233
-
234
- # Then ...
235
- #
236
- # @param [String] description
237
- # A brief description of the _then_ criteria.
238
- #
239
- def Then(description, &procedure)
240
- @_advice[:then][description] = procedure
241
- end
242
-
243
- alias :hence :Then
244
-
245
- # Access to advice.
246
- def [](key)
247
- @_advice[key]
248
- end
249
-
250
197
  end
251
198
 
252
199
  end
@@ -0,0 +1,68 @@
1
+ module Lime
2
+
3
+ # Convenience method for creating a feature mixin.
4
+ #
5
+ # @example
6
+ #
7
+ # module MyStepDefinitions
8
+ # include Lime::Featurette
9
+ #
10
+ # Given "customer's name is '(((\s+)))'" do |name|
11
+ # @name = name
12
+ # end
13
+ # end
14
+ #
15
+ # Feature do
16
+ # include MyStepDefinitions
17
+ # end
18
+ #
19
+ module Featurette
20
+
21
+ def self.append_features(base)
22
+ base.extend(self)
23
+ base.module_eval %{
24
+ @_advice = Hash.new{ |h,k| h[k] = {} }
25
+ }
26
+ end
27
+
28
+ # Given ...
29
+ #
30
+ # @param [String] description
31
+ # A brief description of the _given_ criteria.
32
+ #
33
+ def Given(description, &procedure)
34
+ @_advice[:given][description] = procedure
35
+ end
36
+
37
+ alias :given :Given
38
+
39
+ # When ...
40
+ #
41
+ # @param [String] description
42
+ # A brief description of the _when_ criteria.
43
+ #
44
+ def When(description, &procedure)
45
+ @_advice[:when][description] = procedure
46
+ end
47
+
48
+ alias :wence :When
49
+
50
+ # Then ...
51
+ #
52
+ # @param [String] description
53
+ # A brief description of the _then_ criteria.
54
+ #
55
+ def Then(description, &procedure)
56
+ @_advice[:then][description] = procedure
57
+ end
58
+
59
+ alias :hence :Then
60
+
61
+ # Access to advice.
62
+ def [](key)
63
+ @_advice[key]
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -14,8 +14,7 @@ module Lime
14
14
 
15
15
  @steps = []
16
16
 
17
- @scope = Scope.new(self)
18
- @scope.module_eval(&block)
17
+ @scope = Scope.new(self, &block)
19
18
  end
20
19
 
21
20
  # Parent feature.
@@ -66,7 +65,9 @@ module Lime
66
65
  def topic
67
66
  end
68
67
 
68
+ #
69
69
  # Run a step in the context of this scenario.
70
+ #
70
71
  def run(step)
71
72
  type = step.type
72
73
  desc = step.label
@@ -82,6 +83,7 @@ module Lime
82
83
  # features.clauses[@type].find{ |c| c =~ @description }
83
84
  #end
84
85
 
86
+ #
85
87
  # Convert matching string into a regular expression. If the string
86
88
  # contains parentheticals, e.g. `(.*?)`, the text within them is
87
89
  # treated as a case-insensitve back-referenceing regular expression
@@ -89,6 +91,7 @@ module Lime
89
91
  #
90
92
  # To use a regular expression, but leave the resulting match out of
91
93
  # the backreferences use `?:`, e.g. `(?:\d+)`.
94
+ #
92
95
  def match_regexp(str)
93
96
  ## the old way required double and triple parens
94
97
  #str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
@@ -102,15 +105,17 @@ module Lime
102
105
  end
103
106
 
104
107
  # TODO: Need to ensure the correct order of Given, When, Then.
108
+
109
+ #
105
110
  class Scope < Module
106
111
 
107
112
  #
108
- def initialize(scenario) #, &code)
113
+ def initialize(scenario, &block)
109
114
  @scenario = scenario
110
115
 
111
- extend(scenario.feature.scope)
116
+ #include(scenario.feature.scope)
112
117
 
113
- #module_eval(&code)
118
+ module_eval(&block)
114
119
  end
115
120
 
116
121
  # Given ...