cucumber-tcl 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,6 +23,7 @@ To become a release manager, create a pull request adding your name to the list
23
23
  Current release managers:
24
24
  * [Matt Wynne](https://rubygems.org/profiles/mattwynne)
25
25
  * [Jonathan Owers](https://rubygems.org/profiles/jowers)
26
+ * [Shaun Bristow](https://rubygems.org/profiles/ahhbristow)
26
27
 
27
28
  To grant release privilege, issue the following command:
28
29
 
data/README.md CHANGED
@@ -88,3 +88,15 @@ and in your step definition, you might have
88
88
  puts "The first item I bought was [lindex $items 0]"
89
89
  }
90
90
 
91
+ Resetting state between scenarios
92
+ ---------------------------------
93
+
94
+ Depending on how your test and/or application code is structured, there may be a chance of data persisting between scenarios, which could result in tests that pass or fail unexpectedly. To eliminiate the risk of this, Cucumber TCL will start a new TCL interpreter between every scenario by creating a new instance of the 'framework' object, meaning that the env.tcl file is loaded each time. Whilst this will remove the data leakage risk, it may also cause your scenarios to run slowly if there is a lot of setup required for a scenario to run (eg, setting up fixture data, building a database or loading large amounts of data into memory). To override the default behaviour of starting up a new interpreter, an environment variable can be passed into the 'cucumber' command enabling the sharing of the TCL interpreter via the 'framework' object:
95
+
96
+ cucumber SHARE_FRAMEWORK=1
97
+
98
+ It's also possible to make the default behaviour of starting up a new interpreter explicit:
99
+
100
+ cucumber SHARE_FRAMEWORK=0
101
+
102
+ If you are wrapping Cucumber around poorly understood legacy TCL code, you may wish to enable sharing of the framework object (and thus avoid starting a new TCL interpreter) during development in the interests of running tests quickly, but retain the default behaviour in your CI build to remove the risk of data leakage if you think there is a chance of this.
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.required_ruby_version = ">= 1.9.3"
15
15
 
16
16
  s.add_dependency 'ruby-tcl', '~> 0.1.1'
17
- s.add_dependency 'cucumber', '~> 2.0.0.rc.4'
17
+ s.add_dependency 'cucumber', '~> 2.0.0'
18
18
 
19
19
  s.add_development_dependency 'rspec', '~> 3.2'
20
20
  s.add_development_dependency 'aruba', '~> 0.6'
@@ -1,5 +1,76 @@
1
1
  Feature: Sourcing tcl files
2
2
 
3
+ Scenario: Source files in the appropriate order (no command line options)
4
+ Given a file named "features/test.feature" with:
5
+ """
6
+ Feature:
7
+ Scenario:
8
+ Given testing file sourcing
9
+ """
10
+ And a file named "features/step_definitions/steps_a.tcl" with:
11
+ """
12
+ puts "Sourced step_definitions/steps_a.tcl"
13
+ """
14
+ And a file named "features/step_definitions/steps_b.tcl" with:
15
+ """
16
+ puts "Sourced step_definitions/steps_b.tcl"
17
+ """
18
+ And a file named "features/support/db.tcl" with:
19
+ """
20
+ puts "Sourced support/db.tcl"
21
+ """
22
+ And a file named "features/support/env.rb" with:
23
+ """
24
+ require 'cucumber/tcl'
25
+ """
26
+ And a file named "features/support/env.tcl" with:
27
+ """
28
+ puts "Sourced support/env.tcl"
29
+ """
30
+ When I run `cucumber`
31
+ Then it should pass with:
32
+ """
33
+ Sourced support/env.tcl
34
+ Sourced support/db.tcl
35
+ Sourced step_definitions/steps_a.tcl
36
+ Sourced step_definitions/steps_b.tcl
37
+ """
38
+
39
+ Scenario: Source files in the appropriate order (with command line options)
40
+ Given a file named "myfeatures/group one/test.feature" with:
41
+ """
42
+ Feature:
43
+ Scenario:
44
+ Given testing file sourcing
45
+ """
46
+ And a file named "myfeatures/step definitions/steps.tcl" with:
47
+ """
48
+ puts "Sourced step definitions/steps.tcl"
49
+ """
50
+ And a file named "myfeatures/support/db.tcl" with:
51
+ """
52
+ puts "Sourced support/db.tcl"
53
+ """
54
+ And a file named "myfeatures/support/debug.tcl" with:
55
+ """
56
+ puts "Sourced support/debug.tcl"
57
+ """
58
+ And a file named "myfeatures/support/env.rb" with:
59
+ """
60
+ require 'cucumber/tcl'
61
+ """
62
+ And a file named "myfeatures/support/env.tcl" with:
63
+ """
64
+ puts "Sourced support/env.tcl"
65
+ """
66
+ When I run `cucumber 'myfeatures/group one/test.feature' --require myfeatures --exclude 'debug.*'`
67
+ Then it should pass with:
68
+ """
69
+ Sourced support/env.tcl
70
+ Sourced support/db.tcl
71
+ Sourced step definitions/steps.tcl
72
+ """
73
+
3
74
  Scenario: Display stack trace when there is an error in a sourced file
4
75
  Given a file named "features/test.feature" with:
5
76
  """
@@ -23,7 +94,10 @@ Feature: Sourcing tcl files
23
94
  "error "Fail sourcing""
24
95
  (file "features/support/helper.tcl" line 1)
25
96
  invoked from within
26
- "source $x" (Tcl::Error)
97
+ "source features/support/helper.tcl"
98
+ ("uplevel" body line 1)
99
+ invoked from within
100
+ "uplevel #0 [list source $file]" (Tcl::Error)
27
101
  """
28
102
 
29
103
  Scenario: Display stack trace with multiple levels
@@ -56,5 +130,8 @@ Feature: Sourcing tcl files
56
130
  "test_proc"
57
131
  (file "features/support/helper.tcl" line 5)
58
132
  invoked from within
59
- "source $x" (Tcl::Error)
133
+ "source features/support/helper.tcl"
134
+ ("uplevel" body line 1)
135
+ invoked from within
136
+ "uplevel #0 [list source $file]" (Tcl::Error)
60
137
  """
@@ -3,7 +3,14 @@ Feature: Reset state
3
3
  In order to keep state from leaking between scenarios, by default,
4
4
  we create a new Tcl interpreter for each test case.
5
5
 
6
- Scenario: Set a global variable in one scenario and access it in another
6
+ In order to prevent long setup time before each scenario
7
+ we can optionally avoid starting a new TCL interpreter
8
+
9
+ Rules:
10
+ -- The state is maintained between scenarios if an environment variable is passed into Cucumber
11
+ -- Otherwise a new TCL interpreter is started and state is reset on each scenario
12
+
13
+ Background:
7
14
  Given a file named "features/test.feature" with:
8
15
  """
9
16
  Feature:
@@ -30,8 +37,25 @@ Feature: Reset state
30
37
  """
31
38
  require 'cucumber/tcl'
32
39
  """
40
+
41
+ Scenario: State reset when running 'cucumber' with no options
33
42
  When I run `cucumber`
34
43
  Then it should fail with:
44
+ """
45
+ can't read "::g": no such variable
46
+ """
47
+
48
+ Scenario: State reset when running 'cucumber' with a new framework object for each scenario
49
+ When I run `cucumber SHARE_FRAMEWORK=0`
50
+ Then it should fail with:
51
+ """
52
+ can't read "::g": no such variable
53
+ """
54
+
55
+ Scenario: State not reset when running 'cucumber' and sharing framework object
56
+ When I run `cucumber SHARE_FRAMEWORK=1`
57
+ Then it should pass with:
35
58
  """
36
- can't read "::g": no such variable
59
+ 2 scenarios (2 passed)
60
+ 3 steps (3 passed)
37
61
  """
@@ -13,9 +13,23 @@ module Cucumber
13
13
  module Tcl
14
14
 
15
15
  def self.install(cucumber_config)
16
- create_step_definitions = lambda {
17
- StepDefinitions.new(Framework.new)
18
- }
16
+ # Unless configured off, we should start up a new
17
+ # framework for each scenario, which results
18
+ # in a new TCL interpreter. This can be used
19
+ # to check that there is no data leakage between
20
+ # scenarios when testing poorly understood code
21
+ share_framework = (ENV['SHARE_FRAMEWORK'] == '1')
22
+
23
+ if !share_framework
24
+ create_step_definitions = lambda {
25
+ StepDefinitions.new(Framework.new(cucumber_config))
26
+ }
27
+ else
28
+ framework = Framework.new(cucumber_config)
29
+ create_step_definitions = lambda {
30
+ StepDefinitions.new(framework)
31
+ }
32
+ end
19
33
  cucumber_config.filters << ActivateSteps.new(create_step_definitions)
20
34
  end
21
35
 
@@ -3,8 +3,12 @@ module Cucumber
3
3
  class Framework
4
4
  TCL_FRAMEWORK_PATH = File.dirname(__FILE__) + '/framework.tcl'
5
5
 
6
- def initialize(path = TCL_FRAMEWORK_PATH)
6
+ def initialize(cucumber_config = nil, path = TCL_FRAMEWORK_PATH)
7
7
  @tcl = ::Tcl::Interp.load_from_file(path)
8
+
9
+ all_files_to_load = cucumber_config.nil? ? [] : cucumber_config.all_files_to_load
10
+ all_files_to_load.collect! {|f| f.gsub(/([\\\s{}])/, '\\\\\1')}
11
+ @tcl.proc('source_files').call(all_files_to_load.join(' '))
8
12
  end
9
13
 
10
14
  def step_definition_exists?(step_name)
@@ -10,6 +10,7 @@ namespace eval ::cucumber:: {
10
10
  set TEST 0
11
11
  }
12
12
 
13
+ namespace export source_files
13
14
  namespace export step_definition_exists
14
15
  namespace export execute_step_definition
15
16
  namespace export Given
@@ -102,14 +103,43 @@ proc ::cucumber::_search_steps {step_name {execute 0} {multiline_args {}}} {
102
103
  return 0
103
104
  }
104
105
 
105
- proc ::cucumber::source_steps args {
106
+ # Sort a list of files such that: */support/env.{ext} < */support/{file} < */{file}
107
+ proc ::cucumber::_sort_by_source_priority {a b} {
108
+
109
+ if {[string equal [lindex [file split $a] end-1] "support"]} {
110
+ if {[string equal [file rootname [lindex [file split $a] end]] "env"]} {
111
+ set a_order 1
112
+ } else {
113
+ set a_order 2
114
+ }
115
+ } else {
116
+ set a_order 3
117
+ }
118
+
119
+ if {[string equal [lindex [file split $b] end-1] "support"]} {
120
+ if {[string equal [file rootname [lindex [file split $b] end]] "env"]} {
121
+ set b_order 1
122
+ } else {
123
+ set b_order 2
124
+ }
125
+ } else {
126
+ set b_order 3
127
+ }
128
+
129
+ return [expr {$a_order - $b_order}]
130
+ }
131
+
132
+ proc ::cucumber::source_files {files} {
106
133
  variable TEST
107
134
 
108
135
  if {$TEST ne 1} {
109
- #TODO let that path be configurable from cucumber-ruby
110
- foreach x [glob -nocomplain features/**/*.tcl] {
111
- if {[catch {source $x} msg]} {
112
- error $::errorInfo
136
+ foreach file [lsort -command _sort_by_source_priority $files] {
137
+ if {[string equal [file extension $file] ".tcl"]} {
138
+ if {[catch {
139
+ uplevel #0 [list source $file]
140
+ }]} {
141
+ error $::errorInfo
142
+ }
113
143
  }
114
144
  }
115
145
  }
@@ -120,4 +150,3 @@ proc ::cucumber::pending args {
120
150
  }
121
151
 
122
152
  namespace import ::cucumber::*
123
- ::cucumber::source_steps
@@ -121,6 +121,56 @@ test Then-1 {calling Then adds a new entry to the STEPS list} {
121
121
 
122
122
 
123
123
 
124
+ #
125
+ # Test _sort_by_source_priority procedure
126
+ #
127
+ test _sort_by_source_priority-1 {_sort_by_source_priority prioritises support/env.{ext} over other support/ files} {
128
+ -body {
129
+ set sort [::cucumber::_sort_by_source_priority "test/support/abc.ext" "test/support/env.ext"]
130
+ # only interested if sort is +ve, 0 or -ve; convert to 1, 0 or -1
131
+ expr { $sort == 0 ? 0 : $sort / abs($sort) }
132
+ }
133
+ -result 1
134
+ }
135
+
136
+ test _sort_by_source_priority-2 {_sort_by_source_priority prioritises support/env.{ext} over other support/ files} {
137
+ -body {
138
+ set sort [::cucumber::_sort_by_source_priority "test/support/env.ext" "test/support/abc.ext"]
139
+ # only interested if sort is +ve, 0 or -ve; convert to 1, 0 or -1
140
+ expr { $sort == 0 ? 0 : $sort / abs($sort) }
141
+ }
142
+ -result -1
143
+ }
144
+
145
+ test _sort_by_source_priority-3 {_sort_by_source_priority prioritises support/ files over other files} {
146
+ -body {
147
+ set sort [::cucumber::_sort_by_source_priority "test/features/abc.ext" "test/support/abc.ext"]
148
+ # only interested if sort is +ve, 0 or -ve; convert to 1, 0 or -1
149
+ expr { $sort == 0 ? 0 : $sort / abs($sort) }
150
+ }
151
+ -result 1
152
+ }
153
+
154
+ test _sort_by_source_priority-4 {_sort_by_source_priority prioritises support/ files over other files} {
155
+ -body {
156
+ set sort [::cucumber::_sort_by_source_priority "test/support/abc.ext" "test/features/abc.ext"]
157
+ # only interested if sort is +ve, 0 or -ve; convert to 1, 0 or -1
158
+ expr { $sort == 0 ? 0 : $sort / abs($sort) }
159
+ }
160
+ -result -1
161
+ }
162
+
163
+ test _sort_by_source_priority-5 {_sort_by_source_priority prioritises non support/ files equally} {
164
+ -body {
165
+ set sort [::cucumber::_sort_by_source_priority "test/lib/abc.ext" "test/etc/abc.ext"]
166
+ # only interested if sort is +ve, 0 or -ve; convert to 1, 0 or -1
167
+ expr { $sort == 0 ? 0 : $sort / abs($sort) }
168
+ }
169
+ -result 0
170
+ }
171
+
172
+
173
+
124
174
  #
125
175
  # Test _search_steps procedure
126
176
  #
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
@@ -1,3 +1,6 @@
1
+ proc source_files { files } {
2
+ }
3
+
1
4
  proc execute_step_definition { step_name } {
2
5
  }
3
6
 
@@ -12,7 +12,7 @@ module Cucumber::Tcl
12
12
 
13
13
  it "can activate a passing tcl step" do
14
14
  path = File.dirname(__FILE__) + '/fixtures/everything_ok.tcl'
15
- tcl_framework = Framework.new(path)
15
+ tcl_framework = Framework.new(nil, path)
16
16
  step_definitions = StepDefinitions.new(tcl_framework)
17
17
  expect(step_definitions.attempt_to_activate(test_step).location).to eq location
18
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-tcl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-06-08 00:00:00.000000000 Z
14
+ date: 2017-04-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: ruby-tcl
@@ -36,7 +36,7 @@ dependencies:
36
36
  requirements:
37
37
  - - ~>
38
38
  - !ruby/object:Gem::Version
39
- version: 2.0.0.rc.4
39
+ version: 2.0.0
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,7 +44,7 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 2.0.0.rc.4
47
+ version: 2.0.0
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rspec
50
50
  requirement: !ruby/object:Gem::Requirement
@@ -165,6 +165,6 @@ rubyforge_project:
165
165
  rubygems_version: 1.8.23
166
166
  signing_key:
167
167
  specification_version: 3
168
- summary: cucumber-tcl-0.0.6
168
+ summary: cucumber-tcl-0.0.7
169
169
  test_files: []
170
170
  has_rdoc: