two-step 1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bbcd87fc9e0ece6a20bedfe6664901250297a175
4
+ data.tar.gz: 2beecdace7f917e4773d529b0e96377c6d9ef938
5
+ SHA512:
6
+ metadata.gz: 03775343f6f5fb263872e1cfcc2ae48e008e7693f0e3e4373eec8b41827ad4018bd51563a0adcb0cb90e09689aa491f8c877c8fa0259e39ae9d404be008ed3fa
7
+ data.tar.gz: cba2e257f83704719a484584f257e64df337dd2585aa93dcbbdbb3c62cfc5556ce699176db2950c6a68d3dbc183e7d02fc408cb52fa82aeda198542d80041b0c
@@ -0,0 +1,116 @@
1
+ # Two Step
2
+ ## ( or: why would I want to relearn how to write specs? )
3
+
4
+ Two-Step allows you to chain examples into a series of steps that run
5
+ in sequence and which stop when a step fails. It's often incredibly
6
+ useful to be able to aseemble a series of tests that should all pass,
7
+ but where completely isolating them is less than sensible.
8
+
9
+ ( Two Step is the RSpec 2 compatible version of RSpec Steps - which can be
10
+ found here: https://github.com/LRDesign/rspec-steps )
11
+
12
+ One excellent example is web site integration tests. With RSpec steps you can
13
+ do:
14
+
15
+ steps "Login and change password" do
16
+ it "should show the login form" do
17
+ visit root
18
+ page.should have_text "Login"
19
+ end
20
+
21
+ it "should successfully log in" do
22
+ fill_in :name, "Johnny User"
23
+ click "Login"
24
+ page.should have_text "Welcome, Johnny!"
25
+ end
26
+
27
+ it "should load the password change form" do
28
+ click "My Settings"
29
+ click "Update Password"
30
+ page.should have_selector("form#update_password")
31
+ end
32
+
33
+ it "should change the user's password successfully" do
34
+ fill_in :password, "foobar"
35
+ fill_in :password_confirmation, "foobar"
36
+ click "Change Password"
37
+ page.should have_text "Password changed successfully!"
38
+ User.find_by_name("Johnny User").valid_password?("foobar").should be_true
39
+ end
40
+
41
+ end
42
+
43
+ The examples above will be run in order. State is preserved between examples
44
+ inside a "steps" block: any DB transactions will not roll back until the entire
45
+ sequence has been complete.
46
+
47
+ If any example inside the "steps" block fails, all remaining steps will be marked
48
+ pending and therefore skipped.
49
+
50
+ ## Rationale
51
+
52
+ RSpec's philosophy is that all examples should be completely independent. This
53
+ is a great philosophy for most purposes, and we recommend you stick to it in
54
+ almost all cases. BUT, that complete separation of examples really sucks when
55
+ you're trying to write long stories involving many requests. You are usually
56
+ stuck with three choices:
57
+
58
+ 1. Write a sequence of examples, each of which repeats the behavior of all previous examples. Downside: horrendously inefficient.
59
+ 2. Write a single huge example which performs the entire story. Downside: only one description, no independent reporting of the steps of the story.
60
+ 3. Use Cucumber. Downside: We agree totally with this guy: http://bit.ly/dmXqnY
61
+
62
+ Two-Step intentionally breaks RSpec's "independent" philosophy to let us get the
63
+ only thing we really want from Cucumber - the ability to execute some examples in sequence,
64
+ and skip subsequent steps after a failure.
65
+
66
+ ## Caveats and cautions
67
+
68
+ Don't call "describe" inside of "steps". The behavior is undefined and probably bad. It's
69
+ hard to imagine what this should actually mean in any case. Future versions of rspec-steps
70
+ will consider this an error.
71
+
72
+ Any call to "before" inside a steps block is treated like before(:all) and is run only
73
+ once before the first step. Or perhaps more accurately, any call to before() is treated
74
+ like before(:each) ... but for these purposes the entire steps block is treated like a
75
+ single example.
76
+
77
+ ## Advanced stuff: shared steps
78
+
79
+ If you have (for example) two user stories that share the same first N steps but then
80
+ diverge, you can DRY your code out with shared_steps blocks, like so:
81
+
82
+ shared_steps "For a logged-in user" do
83
+ it "should have login form"
84
+ visit root
85
+ page.should have_selector "form#login"
86
+ end
87
+
88
+ it "should log the user in" do
89
+ fill_in :name, "Johnny User"
90
+ page.should have_text "Welcome, Johnny!"
91
+ end
92
+ end
93
+
94
+ steps "updating password" do
95
+ perform_steps "For a logged-in user"
96
+
97
+ it "should update the password" do
98
+ ...
99
+ end
100
+ end
101
+
102
+ steps "uploading a profile picture" do
103
+ perform_steps "For a logged-in user"
104
+
105
+ it "should upload a picture" do
106
+ ...
107
+ end
108
+ end
109
+
110
+ ## Versions and Dependencies
111
+
112
+ The goal (sadly unfulfilled) is to try to be compatible with as many versions
113
+ of RSpec 2.x as possible. Frankly, Two-Step is more than a little bit of a
114
+ hack, and intrudes wholesale on RSpec's private interfaces. We make good use of
115
+ Travis to check compatibility, however. You can check what versions of RSpec
116
+ and Ruby Two-Step works with here: https://travis-ci.org/LRDesign/two-step
@@ -0,0 +1,17 @@
1
+
2
+ RSpec::Core::ExampleGroup defined as stepwise
3
+ ::steps
4
+ should create an ExampleGroup that includes RSpec::Stepwise
5
+ with Stepwise included
6
+ should retain instance variables between steps
7
+ should mark later examples as pending if one fails
8
+ should allow nested steps
9
+ should not allow nested normal contexts (PENDING: A correct approach - in the meantime, this behavior is undefined)
10
+
11
+ Pending:
12
+ RSpec::Core::ExampleGroup defined as stepwise with Stepwise included should not allow nested normal contexts
13
+ # A correct approach - in the meantime, this behavior is undefined
14
+ # ./spec/example_group.rb:63
15
+
16
+ Finished in 0.10849 seconds
17
+ 5 examples, 0 failures, 1 pending
@@ -0,0 +1,3 @@
1
+ require 'two-step/duckpunch/object-extensions'
2
+ require 'two-step/duckpunch/example-group'
3
+ require 'two-step/duckpunch/example'
@@ -0,0 +1,27 @@
1
+ require 'rspec/core'
2
+ require 'two-step/stepwise'
3
+
4
+ module TwoStep
5
+ module DSL
6
+ def steps(*args, &block)
7
+ options =
8
+ if args.last.is_a?(Hash)
9
+ args.pop
10
+ else
11
+ {}
12
+ end
13
+ options[:stepwise] = true
14
+ options[:caller] ||= caller
15
+ args.push(options)
16
+
17
+ describe(*args, &block)
18
+ end
19
+ end
20
+ end
21
+
22
+ RSpec::Core::ExampleGroup.extend TwoStep::DSL
23
+
24
+ extend TwoStep::DSL
25
+ Module::send(:include, TwoStep::DSL)
26
+
27
+ RSpec::configuration.include(RSpecStepwise, :stepwise => true)
@@ -0,0 +1,5 @@
1
+ RSpec::Core::Example.class_eval do
2
+ def exception
3
+ @exception
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'two-step/duckpunch/example-group'
2
+ require 'two-step/stepwise'
3
+ require 'rspec/core/shared_example_group'
4
+
5
+ module RSpec::Core::SharedExampleGroup
6
+ alias :shared_steps :share_examples_for
7
+ alias :steps_shared_as :share_as
8
+ end
@@ -0,0 +1,219 @@
1
+ module RSpecStepwise
2
+ class ApatheticReporter < ::RSpec::Core::Reporter
3
+ def notify(*args)
4
+ #noop
5
+ end
6
+ end
7
+
8
+ class WholeListExample < RSpec::Core::Example
9
+ def initialize(example_group_class, descriptions, metadata)
10
+ super
11
+ @reporter = ApatheticReporter.new
12
+ build_example_block
13
+ end
14
+
15
+ def start(reporter)
16
+ super(@reporter)
17
+ end
18
+
19
+ def finish(reporter)
20
+ super(@reporter)
21
+ end
22
+
23
+ def build_example_block
24
+ #variables of concern: reporter, instance
25
+ @example_block = proc do
26
+ begin
27
+ self.class.filtered_examples.inject(true) do |success, example|
28
+ break if RSpec.wants_to_quit
29
+ example.extend StepExample
30
+ unless success
31
+ example.metadata[:pending] = true
32
+ example.metadata[:execution_result][:pending_message] = "Previous step failed"
33
+ end
34
+ succeeded = with_indelible_ivars do
35
+ example.run(self, reporter)
36
+ end
37
+ RSpec.wants_to_quit = true if self.class.fail_fast? && !succeeded
38
+ success && succeeded
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ module StepExample
46
+ def run_before_each
47
+ @example_group_class.run_before_step(self)
48
+ rescue Object => ex
49
+ puts "\n#{__FILE__}:#{__LINE__} => #{[ex, ex.backtrace].pretty_inspect}"
50
+ end
51
+
52
+ def run_after_each
53
+ @example_group_class.run_after_step(self)
54
+ end
55
+
56
+ def with_around_hooks
57
+ yield
58
+ end
59
+ end
60
+
61
+ module ClassMethods
62
+ #This is hacky and needs a more general solution
63
+ #Something like cloning the current conf and having RSpec::Stepwise::config ?
64
+ def suspend_transactional_fixtures
65
+ if self.respond_to? :use_transactional_fixtures
66
+ begin
67
+ old_val = self.use_transactional_fixtures
68
+ self.use_transactional_fixtures = false
69
+
70
+ yield
71
+ ensure
72
+ self.use_transactional_fixtures = old_val
73
+ end
74
+ else
75
+ yield
76
+ end
77
+ end
78
+
79
+ def build_before_hook(options, &block)
80
+ if defined? RSpec::Core::Hooks::BeforeHookExtension
81
+ block.extend(RSpec::Core::Hooks::BeforeHookExtension).with(options)
82
+ else
83
+ RSpec::Core::Hooks::BeforeHook.new(block, options)
84
+ end
85
+ end
86
+
87
+ def build_after_hook(options, &block)
88
+ if defined? RSpec::Core::Hooks::AfterHookExtension
89
+ block.extend(RSpec::Core::Hooks::AfterHookExtension).with(options)
90
+ else
91
+ RSpec::Core::Hooks::AfterHook.new(block, options)
92
+ end
93
+ end
94
+
95
+
96
+ def before(*args, &block)
97
+ if args.first == :step
98
+ args.shift
99
+ options = build_metadata_hash_from(args)
100
+ return ((hooks[:before][:step] ||= []) << build_before_hook(options, &block))
101
+ end
102
+ if args.first == :each
103
+ puts "before blocks declared for steps are always treated as :all scope"
104
+ end
105
+ super
106
+ end
107
+
108
+ def after(*args, &block)
109
+ if args.first == :step
110
+ args.shift
111
+ options = build_metadata_hash_from(args)
112
+ hooks[:after][:step] ||= []
113
+ return (hooks[:after][:step].unshift build_after_hook(options, &block))
114
+ end
115
+ if args.first == :each
116
+ puts "after blocks declared for steps are always treated as :all scope"
117
+ end
118
+ super
119
+ end
120
+
121
+ def around(*args, &block)
122
+ if args.first == :each
123
+ puts "around :each blocks declared for steps are treated as :all scope"
124
+ end
125
+ super
126
+ end
127
+
128
+ def example_synonym(named, desc=nil, *args, &block)
129
+ unless desc.nil?
130
+ desc = [named, desc].join(" ")
131
+ end
132
+ it(desc, *args, &block)
133
+ end
134
+
135
+ def when(*args, &block); example_synonym("when", *args, &block); end
136
+ def then(*args, &block); example_synonym("then", *args, &block); end
137
+ def next(*args, &block); example_synonym("next", *args, &block); end
138
+ def step(*args, &block); example_synonym("step", *args, &block); end
139
+
140
+ def run_step(example, hook, &sorting)
141
+ groups = if respond_to?(:parent_groups)
142
+ parent_groups
143
+ else
144
+ ancestors
145
+ end
146
+
147
+ if block_given?
148
+ groups = yield groups
149
+ end
150
+
151
+ RSpec::Core::Hooks::HookCollection.new(groups.map {|a| a.hooks[hook][:step]}.flatten.compact).for(example).run
152
+ end
153
+
154
+ def run_before_step(example)
155
+ run_step(example, :before)
156
+ end
157
+
158
+ def run_after_step(example)
159
+ run_step(example, :after) do |groups|
160
+ groups.reverse
161
+ end
162
+ end
163
+
164
+ def perform_steps(name, *args, &customization_block)
165
+ shared_block = nil
166
+ if world.respond_to? :shared_example_groups
167
+ shared_block = world.shared_example_groups[name]
168
+ else
169
+ shared_block = shared_example_groups[name]
170
+ end
171
+ raise "Could not find shared example group named #{name.inspect}" unless shared_block
172
+
173
+ module_eval_with_args(*args, &shared_block)
174
+ module_eval(&customization_block) if customization_block
175
+ end
176
+
177
+ def run_examples(reporter)
178
+ whole_list_example = WholeListExample.new(self, "step list", {})
179
+
180
+ instance = new
181
+ set_ivars(instance, before_all_ivars)
182
+ instance.example = whole_list_example
183
+ instance.reporter = reporter
184
+
185
+ result = suspend_transactional_fixtures do
186
+ whole_list_example.run(instance, reporter)
187
+ end
188
+
189
+ unless whole_list_example.exception.nil?
190
+ RSpec.wants_to_quit = true if fail_fast?
191
+ fail_filtered_examples(whole_list_example.exception, reporter)
192
+ end
193
+
194
+ result
195
+ end
196
+ end
197
+
198
+ attr_accessor :reporter
199
+
200
+ def with_indelible_ivars
201
+ old_value, @ivars_indelible = @ivars_indelible, true
202
+ result = yield
203
+ @ivars_indelible = old_value
204
+ result
205
+ rescue Object
206
+ @ivars_indelible = old_value
207
+ raise
208
+ end
209
+
210
+ def instance_variable_set(name, value)
211
+ if !@ivars_indelible
212
+ super
213
+ end
214
+ end
215
+
216
+ def self.included(base)
217
+ base.extend(ClassMethods)
218
+ end
219
+ end
@@ -0,0 +1,164 @@
1
+ require 'two-step'
2
+ require 'rspec-sandbox'
3
+
4
+ describe RSpec::Core::ExampleGroup do
5
+ describe "::steps" do
6
+ it "should create an ExampleGroup that includes RSpec::Stepwise" do
7
+ group = nil
8
+ sandboxed do
9
+ group = RSpec.steps "Test Steps" do
10
+ end
11
+ end
12
+ (class << group; self; end).included_modules.should include(RSpecStepwise::ClassMethods)
13
+ end
14
+ end
15
+
16
+ describe "with Stepwise included" do
17
+ it "should retain instance variables between steps" do
18
+ group = nil
19
+ sandboxed do
20
+ group = RSpec.steps "Test Steps" do
21
+ it("sets @a"){ @a = 1 }
22
+ it("reads @a"){ @a.should == 1}
23
+ end
24
+ group.run
25
+ end
26
+
27
+ group.examples.each do |example|
28
+ example.metadata[:execution_result][:status].should == 'passed'
29
+ end
30
+ end
31
+
32
+ it "should work with shared_steps/perform steps" do
33
+ group = nil
34
+ sandboxed do
35
+ group = RSpec.steps "Test Steps" do
36
+ shared_steps "add one" do
37
+ it("adds one to @a"){ @a += 1 }
38
+ end
39
+ it("sets @a"){ @a = 1 }
40
+ perform_steps "add one"
41
+ perform_steps "add one"
42
+ perform_steps "add one"
43
+ it("reads @a"){ @a.should == 4 }
44
+ end
45
+ group.run
46
+ end
47
+
48
+ group.examples.each do |example|
49
+ example.metadata[:execution_result][:status].should == 'passed'
50
+ end
51
+ end
52
+
53
+ it "should run each_step hooks" do
54
+ group = nil
55
+ afters = []
56
+ befores = []
57
+
58
+ sandboxed do
59
+ group = RSpec.steps "Test Each Step" do
60
+ before :each do
61
+ befores << :each
62
+ end
63
+ after :each do
64
+ afters << :each
65
+ end
66
+
67
+ before :all do
68
+ befores << :all
69
+ end
70
+ after :all do
71
+ afters << :all
72
+ end
73
+
74
+ before :step do
75
+ befores << :step
76
+ end
77
+ after :step do
78
+ afters << :step
79
+ end
80
+
81
+ it "should 1" do
82
+ 1.should == 1
83
+ end
84
+ it "should 2" do
85
+ 2.should == 2
86
+ end
87
+ it "should 3" do
88
+ 3.should == 3
89
+ end
90
+ end
91
+ group.run
92
+ end
93
+
94
+ befores.find_all{|item| item == :all}.length.should == 1
95
+ befores.find_all{|item| item == :each}.length.should == 1
96
+ befores.find_all{|item| item == :step}.length.should == 3
97
+ afters.find_all{|item| item == :all}.length.should == 1
98
+ afters.find_all{|item| item == :each}.length.should == 1
99
+ afters.find_all{|item| item == :step}.length.should == 3
100
+ end
101
+
102
+ it "should mark later examples as failed if a before hook fails" do
103
+ group = nil
104
+ exception = Exception.new "Testing Error"
105
+
106
+ sandboxed do
107
+ group = RSpec.steps "Test Steps" do
108
+ before { raise exception }
109
+ it { 1.should == 1 }
110
+ it { 1.should == 1 }
111
+ end
112
+ group.run
113
+ end
114
+
115
+ group.examples.each do |example|
116
+ example.metadata[:execution_result][:status].should == 'failed'
117
+ example.metadata[:execution_result][:exception].should == exception
118
+ end
119
+ end
120
+
121
+ it "should mark later examples as pending if one fails" do
122
+ group = nil
123
+ sandboxed do
124
+ group = RSpec.steps "Test Steps" do
125
+ it { fail "All others fail" }
126
+ it { 1.should == 1 }
127
+ end
128
+ group.run
129
+ end
130
+
131
+ group.examples[1].metadata[:pending].should == true
132
+ end
133
+
134
+ it "should allow nested steps", :pending => "Not really" do
135
+ group = nil
136
+ sandboxed do
137
+ group = RSpec.steps "Test Steps" do
138
+ steps "Nested" do
139
+ it { @a = 1 }
140
+ it { @a.should == 1}
141
+ end
142
+ end
143
+ group.run
144
+ end
145
+
146
+ group.children[0].examples.each do |example|
147
+ example.metadata[:execution_result][:status].should == 'passed'
148
+ end
149
+ group.children[0].should have(2).examples
150
+ end
151
+
152
+ it "should not allow nested normal contexts" do
153
+ pending "A correct approach - in the meantime, this behavior is undefined"
154
+ expect {
155
+ sandboxed do
156
+ RSpec.steps "Basic" do
157
+ describe "Not allowed" do
158
+ end
159
+ end
160
+ end
161
+ }.to raise_error
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,164 @@
1
+ require 'ftools'
2
+ require 'fileutils'
3
+
4
+ module FileSandbox
5
+ def self.included(spec)
6
+ return unless spec.respond_to? :before
7
+
8
+ spec.before do
9
+ setup_sandbox
10
+ end
11
+
12
+ spec.after do
13
+ teardown_sandbox
14
+ end
15
+ end
16
+
17
+ class HaveContents
18
+ def initialize(contents)
19
+ @contents = contents
20
+ end
21
+
22
+ def matches?(target)
23
+ case @contents
24
+ when Regexp
25
+ @contents =~ target.contents
26
+ when String
27
+ @contents == target.contents
28
+ end
29
+ end
30
+ end
31
+
32
+ def have_contents(expected)
33
+ HaveContents.new(expected)
34
+ end
35
+
36
+ attr_reader :sandbox
37
+
38
+ def in_sandbox(&block)
39
+ raise "I expected to create a sandbox as you passed in a block to me" if !block_given?
40
+
41
+ setup_sandbox
42
+ original_error = nil
43
+
44
+ begin
45
+ yield @sandbox
46
+ rescue => e
47
+ original_error = e
48
+ raise
49
+ ensure
50
+ begin
51
+ teardown_sandbox
52
+ rescue
53
+ if original_error
54
+ STDERR.puts "ALERT: a test raised an error and failed to release some lock(s) in the sandbox directory"
55
+ raise(original_error)
56
+ else
57
+ raise
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def setup_sandbox(path = '__sandbox')
64
+ unless @sandbox
65
+ @sandbox = Sandbox.new(path)
66
+ @__old_path_for_sandbox = Dir.pwd
67
+ Dir.chdir(@sandbox.root)
68
+ end
69
+ end
70
+
71
+ def teardown_sandbox
72
+ if @sandbox
73
+ Dir.chdir(@__old_path_for_sandbox)
74
+ @sandbox.clean_up
75
+ @sandbox = nil
76
+ end
77
+ end
78
+
79
+ class Sandbox
80
+ attr_reader :root
81
+
82
+ def initialize(path = '__sandbox')
83
+ @root = File.expand_path(path)
84
+ clean_up
85
+ FileUtils.mkdir_p @root
86
+ end
87
+
88
+ def [](name)
89
+ SandboxFile.new(File.join(@root, name), name)
90
+ end
91
+
92
+ # usage new :file=>'my file.rb', :with_contents=>'some stuff'
93
+ def new(options)
94
+ if options.has_key? :directory
95
+ dir = self[options.delete(:directory)]
96
+ FileUtils.mkdir_p dir.path
97
+ else
98
+ file = self[options.delete(:file)]
99
+ if (binary_content = options.delete(:with_binary_content) || options.delete(:with_binary_contents))
100
+ file.binary_content = binary_content
101
+ else
102
+ file.content = (options.delete(:with_content) || options.delete(:with_contents) || '')
103
+ end
104
+ end
105
+
106
+ raise "unexpected keys '#{options.keys.join(', ')}'" unless options.empty?
107
+
108
+ dir || file
109
+ end
110
+
111
+ def remove(options)
112
+ name = File.join(@root, options[:file])
113
+ FileUtils.remove_file name
114
+ end
115
+
116
+ def clean_up
117
+ FileUtils.rm_rf @root
118
+ if File.exists? @root
119
+ raise "Could not remove directory #{@root.inspect}, something is probably still holding a lock on it"
120
+ end
121
+ end
122
+ end
123
+
124
+
125
+ class SandboxFile
126
+ attr_reader :path
127
+
128
+ def initialize(path, sandbox_path)
129
+ @path = path
130
+ @sandbox_path = sandbox_path
131
+ end
132
+
133
+ def inspect
134
+ "SandboxFile: #@sandbox_path"
135
+ end
136
+
137
+ def exist?
138
+ File.exist? path
139
+ end
140
+
141
+ def content
142
+ File.read path
143
+ end
144
+
145
+ def content=(content)
146
+ FileUtils.mkdir_p File.dirname(@path)
147
+ File.open(@path, "w") {|f| f << content}
148
+ end
149
+
150
+ def binary_content=(content)
151
+ FileUtils.mkdir_p File.dirname(@path)
152
+ File.open(@path, "wb") {|f| f << content}
153
+ end
154
+
155
+ def create
156
+ self.content = ''
157
+ end
158
+
159
+ alias exists? exist?
160
+ alias contents content
161
+ alias contents= content=
162
+ alias binary_contents= binary_content=
163
+ end
164
+ end
@@ -0,0 +1,17 @@
1
+ puts Dir::pwd
2
+ require 'test/unit'
3
+ begin
4
+ require 'spec'
5
+ rescue LoadError
6
+ false
7
+ end
8
+
9
+ class RSpecTest < Test::Unit::TestCase
10
+ def test_that_rspec_is_available
11
+ assert_nothing_raised("\n\n * RSpec isn't available - please run: gem install rspec *\n\n"){ ::Spec }
12
+ end
13
+
14
+ def test_that_specs_pass
15
+ assert(system(*%w{spec -f e -p **/*.rb spec}),"\n\n * Specs failed *\n\n")
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ require 'rspec/core'
2
+
3
+ class NullObject
4
+ private
5
+ def method_missing(method, *args, &block)
6
+ # ignore
7
+ end
8
+ end
9
+
10
+ def sandboxed(&block)
11
+ @orig_config = RSpec.configuration
12
+ @orig_world = RSpec.world
13
+ new_config = RSpec::Core::Configuration.new
14
+ new_world = RSpec::Core::World.new(new_config)
15
+ RSpec.instance_variable_set(:@configuration, new_config)
16
+ RSpec.instance_variable_set(:@world, new_world)
17
+
18
+ load 'two-step/duckpunch/example-group.rb'
19
+
20
+ object = Object.new
21
+ object.extend(RSpec::Core::SharedExampleGroup)
22
+ object.extend(TwoStep::DSL)
23
+ object.extend(RSpec::Core::DSL)
24
+
25
+ (class << RSpec::Core::ExampleGroup; self; end).class_eval do
26
+ alias_method :orig_run, :run
27
+ def run(reporter=nil)
28
+ @orig_mock_space = RSpec::Mocks::space
29
+ RSpec::Mocks::space = RSpec::Mocks::Space.new
30
+ orig_run(reporter || NullObject.new)
31
+ ensure
32
+ RSpec::Mocks::space = @orig_mock_space
33
+ end
34
+ end
35
+
36
+ object.instance_eval(&block)
37
+ ensure
38
+ (class << RSpec::Core::ExampleGroup; self; end).class_eval do
39
+ remove_method :run
40
+ alias_method :run, :orig_run
41
+ remove_method :orig_run
42
+ end
43
+
44
+ RSpec.instance_variable_set(:@configuration, @orig_config)
45
+ RSpec.instance_variable_set(:@world, @orig_world)
46
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+
3
+ #Ungemmer::ungem_gemspec
@@ -0,0 +1,36 @@
1
+ class Ungemmer
2
+ def self.ungem(*names)
3
+ deps = names.map do |name|
4
+ Gem::Dependency.new(name, nil)
5
+ end
6
+
7
+ deps.each do |dep|
8
+ Gem.source_index.search(dep).each do |gemspec|
9
+ puts " ** Ungemming #{gemspec.full_name} **"
10
+ Gem.source_index.remove_spec(gemspec.full_name)
11
+ end
12
+ end
13
+
14
+ Gem.instance_eval do
15
+ if defined? Gem::MUTEX
16
+ Gem::MUTEX.synchronize do
17
+ @searcher = nil
18
+ end
19
+ else
20
+ @searcher = nil
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.ungem_gemspec
26
+ Dir[File::expand_path(__FILE__ + "../../../*.gemspec")].each do |gemspec_path|
27
+ puts "Ungemming based on #{gemspec_path}"
28
+ begin
29
+ spec = Gem::Specification::load(gemspec_path)
30
+ Ungemmer::ungem(spec)
31
+ rescue LoadError
32
+ puts "Couldn't load #{gemspec_path}"
33
+ end
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: two-step
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Judson Lester
8
+ - Evan Dorn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-11-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: corundum
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: 0.4.0
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 0.4.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: metric_fu
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 4.11.1
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 4.11.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '2.6'
49
+ - - <
50
+ - !ruby/object:Gem::Version
51
+ version: '3'
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '2.6'
59
+ - - <
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ description: |2
63
+ I don't like Cucumber. I don't need plain text stories. My clients either
64
+ read code or don't read any test documents, so Cucumber is mostly useless to me.
65
+ But often, especially in full integration tests, it would be nice to have
66
+ steps in a test.
67
+ email:
68
+ - judson@lrdesign.com
69
+ - evan@lrdesign.com
70
+ executables: []
71
+ extensions: []
72
+ extra_rdoc_files:
73
+ - doc/README
74
+ - doc/Specifications
75
+ files:
76
+ - lib/two-step.rb
77
+ - lib/two-step/stepwise.rb
78
+ - lib/two-step/duckpunch/example-group.rb
79
+ - lib/two-step/duckpunch/example.rb
80
+ - lib/two-step/duckpunch/object-extensions.rb
81
+ - doc/README
82
+ - doc/Specifications
83
+ - spec/example_group_spec.rb
84
+ - spec_help/spec_helper.rb
85
+ - spec_help/gem_test_suite.rb
86
+ - spec_help/rspec-sandbox.rb
87
+ - spec_help/ungemmer.rb
88
+ - spec_help/file-sandbox.rb
89
+ homepage: https://github.com/LRDesign/two-step
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options:
95
+ - --inline-source
96
+ - --main
97
+ - doc/README
98
+ - --title
99
+ - two-step-1.0 RDoc
100
+ require_paths:
101
+ - lib/
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project: two-step
114
+ rubygems_version: 2.0.14
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: I want steps in RSpec 2.x
118
+ test_files:
119
+ - spec_help/gem_test_suite.rb