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.
- data/CONTRIBUTING.md +1 -0
- data/README.md +12 -0
- data/cucumber-tcl.gemspec +1 -1
- data/features/file_sourcing.feature +79 -2
- data/features/reset_state.feature +26 -2
- data/lib/cucumber/tcl.rb +17 -3
- data/lib/cucumber/tcl/framework.rb +5 -1
- data/lib/cucumber/tcl/framework.tcl +35 -6
- data/lib/cucumber/tcl/test/test_framework.tcl +50 -0
- data/lib/cucumber/tcl/version +1 -1
- data/spec/cucumber/tcl/fixtures/everything_ok.tcl +3 -0
- data/spec/cucumber/tcl/step_definitions_spec.rb +1 -1
- metadata +5 -5
data/CONTRIBUTING.md
CHANGED
@@ -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.
|
data/cucumber-tcl.gemspec
CHANGED
@@ -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
|
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
|
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
|
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
|
-
|
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
|
-
|
59
|
+
2 scenarios (2 passed)
|
60
|
+
3 steps (3 passed)
|
37
61
|
"""
|
data/lib/cucumber/tcl.rb
CHANGED
@@ -13,9 +13,23 @@ module Cucumber
|
|
13
13
|
module Tcl
|
14
14
|
|
15
15
|
def self.install(cucumber_config)
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
#
|
data/lib/cucumber/tcl/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
@@ -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.
|
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:
|
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
|
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
|
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.
|
168
|
+
summary: cucumber-tcl-0.0.7
|
169
169
|
test_files: []
|
170
170
|
has_rdoc:
|