bmabey-spork 0.4.4 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README.rdoc +51 -23
  2. data/assets/bootstrap.rb +1 -1
  3. data/bin/spork +0 -0
  4. data/features/cucumber_rails_integration.feature +113 -0
  5. data/features/diagnostic_mode.feature +41 -0
  6. data/features/rails_delayed_loading_workarounds.feature +80 -0
  7. data/features/rspec_rails_integration.feature +90 -0
  8. data/features/steps/rails_steps.rb +53 -0
  9. data/features/steps/sandbox_steps.rb +98 -0
  10. data/features/support/env.rb +98 -0
  11. data/features/unknown_app_framework.feature +42 -0
  12. data/lib/spork.rb +85 -26
  13. data/lib/spork/app_framework.rb +74 -0
  14. data/lib/spork/app_framework/rails.rb +158 -0
  15. data/lib/spork/app_framework/rails_stub_files/application.rb +3 -0
  16. data/lib/spork/app_framework/rails_stub_files/application_controller.rb +3 -0
  17. data/lib/spork/app_framework/rails_stub_files/application_helper.rb +3 -0
  18. data/lib/spork/app_framework/unknown.rb +6 -0
  19. data/lib/spork/custom_io_streams.rb +25 -0
  20. data/lib/spork/diagnoser.rb +103 -0
  21. data/lib/spork/forker.rb +70 -0
  22. data/lib/spork/runner.rb +28 -10
  23. data/lib/spork/server.rb +88 -46
  24. data/lib/spork/server/cucumber.rb +21 -9
  25. data/lib/spork/server/rspec.rb +1 -1
  26. data/spec/spec_helper.rb +93 -35
  27. data/spec/spork/app_framework/rails_spec.rb +22 -0
  28. data/spec/spork/app_framework/unknown_spec.rb +12 -0
  29. data/spec/spork/app_framework_spec.rb +16 -0
  30. data/spec/spork/diagnoser_spec.rb +105 -0
  31. data/spec/spork/forker_spec.rb +44 -0
  32. data/spec/spork/runner_spec.rb +2 -2
  33. data/spec/spork/server/cucumber_spec.rb +25 -0
  34. data/spec/spork/server/rspec_spec.rb +17 -3
  35. data/spec/spork/server_spec.rb +32 -17
  36. data/spec/spork_spec.rb +112 -13
  37. metadata +33 -3
@@ -1,18 +1,35 @@
1
1
  = Spork
2
2
 
3
- * http://github.com/timcharper/spork
3
+ * Repository: http://github.com/timcharper/spork
4
+ * Issues: http://github.com/timcharper/spork/issues
5
+ * Changes: http://github.com/timcharper/spork/blob/master/History.txt
6
+ * Mailing list: http://groups.google.com/group/sporkgem
7
+ * Wiki: http://wiki.github.com/timcharper/spork
4
8
 
5
9
  == SYNOPSIS:
6
10
 
7
- Spork is Tim Harper's implementation of a Drb spec server (similar to the script/spec_server provided by rspec-rails), except rather than using the Rails constant unloading to reload your files, it forks a copy of the server each time you run your specs. The result? Spork runs more solid: it doesn't get corrupted over time, and it properly handles modules and any voo-doo meta programming you may have put in your app.
11
+ Spork is Tim Harper's implementation of test server (similar to the script/spec_server provided by rspec-rails), except rather than using the Rails constant unloading to reload your files, it forks a copy of the server each time you run your tests. The result? Spork runs more solid: it doesn't get corrupted over time, and it properly handles modules and any voo-doo meta programming you may have put in your app.
8
12
 
9
13
  Because Spork uses Kernel.fork, it only works on POSIX systems. This means Windows users are not invited to this party. Sorry :(
10
14
 
11
- Spork is still experimental, but is performing solid for us.
15
+ == Supported Testing Frameworks
16
+
17
+ * Rspec
18
+ * Cucumber
19
+
20
+ And more to come! Vote for your favorite at http://github.com/timcharper/spork/issues
21
+
22
+ == Supported Application Frameworks
23
+
24
+ Actually, Spork ~can~ work with any application framework. But, it ships with hooks and helpers to help make the experience much more "out of the box"
25
+
26
+ * Rails
27
+
28
+ More can be added! Vote for your favorite at http://github.com/timcharper/spork/issues
12
29
 
13
30
  == INSTALL:
14
31
 
15
- [sudo] gem install timcharper-spork --source http://gems.github.com/
32
+ [sudo] gem install spork
16
33
 
17
34
  alternatively:
18
35
 
@@ -35,37 +52,48 @@ Finally, run spork. A spec DRb server will be running!
35
52
 
36
53
  spork
37
54
 
38
- To get the TextMate RSpec bundle to use spork, go to config->advanced->shell variables, and add TM_RSPEC_OPTS=--drb.
55
+ == Diagnostic mode
39
56
 
40
- To run from the command line, use spec --drb spec/lib/my_spec.rb
57
+ Initially, you may find that a few files don't reload automatically. This is because they are being loaded during Spork startup. To identify which project files are being pre-loaded, and why, run:
41
58
 
42
- Or, you could add --drb to your spec.opts file.
59
+ spork --diagnose
60
+ (or spork -d, for short)
43
61
 
44
- == Some potential issues and ways to overcome them:
62
+ It will output a lot of stuff. At the top you'll find a summary of all project files loaded. Down below, the stack trace for each file (how it got loaded). Spork hooks into Rails and does some magic (TM) to prevent ApplicationController observers, etc from pre-loading. Similar hooks for other ruby frameworks may come as support demands.
63
+
64
+ == Running specs over Spork
65
+
66
+ === RSpec
45
67
 
46
- === ActiveRecord reports "connection has gone away" for the first few specs
68
+ To get the TextMate RSpec bundle to use spork, go to config->advanced->shell variables, and add:
47
69
 
48
- Not sure why this happens, but if you simply add a line to re-establish your database connection on each line as follows, the problem goes away:
70
+ TM_RSPEC_OPTS=--drb.
49
71
 
50
- Spork.each_run do
51
- ActiveRecord::Base.establish_connection # make sure that the db connection is ready.
52
- end
72
+ To run from the command line, use:
53
73
 
54
- === Couldn't find formatter class Spec::Runner::Formatter::TextMateFormatter Make sure the --require option is specified *before* --format
74
+ spec --drb spec/lib/my_spec.rb
55
75
 
56
- On one of our projects, many of us using TextMate with spork, only one developer got this error message while the rest of us ran just fine. I don't know exactly why it happened, but requiring the textmate formatter in the prefork block made it go away, like this:
76
+ Or, you could add the following flag to your +spec.opts+ file.
77
+
78
+ --drb
79
+
80
+ === Cucumber
81
+
82
+ Cucumber --drb support for spork is not official yet (but it works). It's the hottest sauce boiling on the world wide web right now. If you can't wait to try it, head on over to Cucumber core-team member Ben Mabey's drb branch and build your own cucumber gem:
83
+
84
+ http://github.com/bmabey/cucumber/tree/drb_server
85
+
86
+ Use this as a guideline when "Sporking" your features/support/env.rb file
87
+
88
+ http://gist.github.com/123370
89
+
90
+ == Some potential issues and ways to overcome them:
57
91
 
58
- Spork.prefork do
59
- gem "rspec", "= 1.2.6"
60
- require 'spec'
61
- ...
62
- require 'spec/runner/formatter/text_mate_formatter'
63
- ...
64
- end
92
+ See http://wiki.github.com/timcharper/spork/troubleshooting
65
93
 
66
94
  == Kudos to
67
95
 
68
- * Ben Mabey - help with documentation, testing, suggestions, patches, collaborated with Cucumber support.
96
+ * Ben Mabey - help with documentation, testing, suggestions, patches, and bringing Cucumber support.
69
97
  * David Chelimsky - for the fine RSpec testing framework, and the original rspec-rails spec_server implementation, which Spork has built upon.
70
98
  * Lead Media Partners - just for being an awesome place to work.
71
99
 
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'spork'
3
3
 
4
4
  Spork.prefork do
5
- # Loading more in this block will cause your specs to run faster. However,
5
+ # Loading more in this block will cause your tests to run faster. However,
6
6
  # if you change any configuration or code from libraries loaded here, you'll
7
7
  # need to restart spork for it take effect.
8
8
 
data/bin/spork CHANGED
File without changes
@@ -0,0 +1,113 @@
1
+ Feature: Cucumber integration with rails
2
+ As a developer using cucumber and rails
3
+ I want to use Spork with Cucumber
4
+ In order to eliminate the startup cost of my application each time I run them
5
+
6
+ Background: Sporked env.rb
7
+ Given I am in a fresh rails project named "test_rails_project"
8
+ And the application has a model, observer, route, and application helper
9
+ And a file named "features/support/env.rb" with:
10
+ """
11
+ require 'rubygems'
12
+ require 'spork'
13
+
14
+ Spork.prefork do
15
+ # Loading more in this block will cause your tests to run faster. However,
16
+ # if you change any configuration or code from libraries loaded here, you'll
17
+ # need to restart spork for it take effect.
18
+
19
+ # Sets up the Rails environment for Cucumber
20
+ ENV['RAILS_ENV'] = "features"
21
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
22
+
23
+ require 'webrat'
24
+
25
+ Webrat.configure do |config|
26
+ config.mode = :rails
27
+ end
28
+
29
+ require 'webrat/core/matchers'
30
+ require 'cucumber'
31
+ require 'cucumber/formatter/unicode' # Comment out this line if you don't want Cucumber Unicode support
32
+ require 'spec/rails'
33
+ require 'cucumber/rails/rspec'
34
+
35
+ #### this is for this test only #######
36
+ $loaded_stuff << 'prefork block' ######
37
+ #######################################
38
+ end
39
+
40
+ Spork.each_run do
41
+ # This code will be run each time you run your specs.
42
+ require 'cucumber/rails/world'
43
+ Cucumber::Rails.use_transactional_fixtures
44
+ Cucumber::Rails.bypass_rescue # Comment out this line if you want Rails own error handling
45
+ # (e.g. rescue_action_in_public / rescue_responses / rescue_from)
46
+
47
+ #### this is for this test only #######
48
+ $loaded_stuff << 'each_run block' #####
49
+ #######################################
50
+ end
51
+ """
52
+ And a file named "features/cucumber_rails.feature" with:
53
+ """
54
+ Feature: cucumber rails
55
+ Scenario: did it work
56
+ Then it should work
57
+ """
58
+ And a file named "features/support/cucumber_rails_helper.rb" with:
59
+ """
60
+ $loaded_stuff << 'features/support/cucumber_rails_helper.rb'
61
+ """
62
+ And a file named "config/environments/features.rb" with:
63
+ """
64
+ # your cucumber env here
65
+ """
66
+ And a file named "config/database.yml" with:
67
+ """
68
+ features:
69
+ adapter: sqlite3
70
+ database: db/features.sqlite3
71
+ timeout: 5000
72
+ """
73
+ And a file named "features/step_definitions/cucumber_rails_steps.rb" with:
74
+ """
75
+ Then "it should work" do
76
+ Spork.state.should == :using_spork
77
+ RAILS_ENV.should == 'features'
78
+ (Rails.respond_to?(:logger) ? Rails.logger : ActionController::Base.logger).info "hey there"
79
+ $loaded_stuff.should include('ActiveRecord::Base.establish_connection')
80
+ $loaded_stuff.should include('User')
81
+ $loaded_stuff.should include('UserObserver')
82
+ $loaded_stuff.should include('ApplicationHelper')
83
+ $loaded_stuff.should include('config/routes.rb')
84
+ $loaded_stuff.should include('features/support/cucumber_rails_helper.rb')
85
+ $loaded_stuff.should include('each_run block')
86
+ $loaded_stuff.should include('prefork block')
87
+ puts "It worked!"
88
+ end
89
+ """
90
+ Scenario: Analyzing files were preloaded
91
+ When I run spork --diagnose
92
+ Then the output should not contain "user_observer.rb"
93
+ Then the output should not contain "user.rb"
94
+ Then the output should not contain "app/controllers/application.rb"
95
+ Then the output should not contain "app/controllers/application_controller.rb"
96
+ Then the output should not contain "app/controllers/application_helper.rb"
97
+ Then the output should not contain "config/routes.rb"
98
+ Then the output should not contain "features/step_definitions/cucumber_rails_steps.rb"
99
+ Then the output should not contain "features/support/cucumber_rails_helper.rb"
100
+
101
+ Scenario: Running spork with a rails app and observers
102
+ When I fire up a spork instance with "spork cucumber"
103
+ And I run cucumber --drb features/cucumber_rails.feature
104
+ Then the error output should be empty
105
+ And the output should contain "It worked!"
106
+ And the file "log/features.log" should include "hey there"
107
+
108
+ Scenario: Running spork with a rails app and a non-standard port
109
+ When I fire up a spork instance with "spork cucumber -p 9000"
110
+ And I run cucumber --drb --port 9000 features/cucumber_rails.feature
111
+ Then the error output should be empty
112
+ And the output should contain "It worked!"
113
+ And the file "log/features.log" should include "hey there"
@@ -0,0 +1,41 @@
1
+ Feature: Diagnostic Mode
2
+ To help a developer quickly pinpoint why files are being loaded
3
+ Spork provides a diagnostic mode
4
+ That provides a list of which project files were loaded during prefork, and who loaded them.
5
+
6
+ Scenario: Running spork --diagnose
7
+ Given I am in the directory "test_project"
8
+ And a file named "spec/spec_helper.rb" with:
9
+ """
10
+ require 'rubygems'
11
+ require 'spork'
12
+
13
+ Spork.prefork do
14
+ require 'lib/awesome.rb'
15
+ require '../external_dependency/super_duper.rb'
16
+ end
17
+
18
+ Spork.each_run do
19
+ puts "I'm loading the stuff just for this run..."
20
+ end
21
+ """
22
+ And a file named "lib/awesome.rb" with:
23
+ """
24
+ class Awesome
25
+ end
26
+ """
27
+ And a file named "../external_dependency/super_duper.rb" with:
28
+ """
29
+ class Awesome
30
+ end
31
+ """
32
+ When I run spork --diagnose
33
+ Then the error output should contain
34
+ """
35
+ Loading Spork.prefork block...
36
+ """
37
+ And the output should contain "lib/awesome.rb"
38
+ And the output should contain "spec/spec_helper.rb:5"
39
+ And the output should not contain "super_duper.rb"
40
+ And the output should not contain "diagnose.rb"
41
+
@@ -0,0 +1,80 @@
1
+ Feature: Rails Delayed Work arounds
2
+ To allow a rails developer to update as many parts of his application as possible without needing to restart Spork
3
+ Spork automatically tells rails to delay loading certain parts of the application until after the fork occurs
4
+ Providing work arounds
5
+
6
+ Background: Rails App with RSpec and Spork
7
+
8
+ Given I am in a fresh rails project named "test_rails_project"
9
+ And a file named "spec/spec_helper.rb" with:
10
+ """
11
+ require 'rubygems'
12
+ require 'spork'
13
+
14
+ Spork.prefork do
15
+ require File.dirname(__FILE__) + '/../config/environment.rb'
16
+ require 'spec'
17
+ require 'spec/rails'
18
+ end
19
+
20
+ Spork.each_run do
21
+ end
22
+ """
23
+ And the application has a model, observer, route, and application helper
24
+ Scenario: within a view, calling helper methods from an included module in ApplicationHelper
25
+ Given a file named "app/helpers/application_helper.rb" with:
26
+ """
27
+ module ApplicationHelper
28
+ include Reverseatron
29
+ end
30
+ """
31
+ Given a file named "lib/reverseatron.rb" with:
32
+ """
33
+ module Reverseatron
34
+ def reverse_text(txt)
35
+ txt.reverse
36
+ end
37
+ end
38
+ """
39
+ Given a file named "app/controllers/users_controller.rb" with:
40
+ """
41
+ class UsersController < ApplicationController
42
+ $loaded_stuff << 'UsersController'
43
+ def index
44
+ @users = []
45
+ end
46
+ end
47
+ """
48
+ Given a file named "app/controllers/users_helper.rb" with:
49
+ """
50
+ module UsersHelper
51
+ end
52
+ """
53
+ Given a file named "app/views/users/index.html.erb" with:
54
+ """
55
+ <%= reverse_text('listing users'.reverse) %>
56
+ """
57
+ Given a file named "spec/controllers/users_controller_spec.rb" with:
58
+ """
59
+ describe UsersController do
60
+ integrate_views
61
+ it "renders a page, using a method inherited from ApplicationController" do
62
+ get :index
63
+ response.body.should include('listing users')
64
+ puts "Controller stack is functioning"
65
+ response.body.should include('Here is a list of users')
66
+ puts "Views are not being cached"
67
+ end
68
+ end
69
+ """
70
+ When I fire up a spork instance with "spork rspec"
71
+ And the contents of "app/views/users/index.html.erb" are changed to:
72
+ """
73
+ <%= reverse_text('listing users'.reverse) %>
74
+ <p>Here is a list of users</p>
75
+ """
76
+
77
+ And I run spec --drb spec/controllers/users_controller_spec.rb
78
+ Then the output should contain "Controller stack is functioning"
79
+ Then the output should contain "Views are not being cached"
80
+
@@ -0,0 +1,90 @@
1
+ Feature: Rails Integration
2
+ To get a developer up and running quickly
3
+ Spork automatically integrates with rails
4
+ Providing default hooks and behaviors
5
+
6
+ Background: Rails App with RSpec and Spork
7
+
8
+ Given I am in a fresh rails project named "test_rails_project"
9
+ And a file named "spec/spec_helper.rb" with:
10
+ """
11
+ require 'rubygems'
12
+ require 'spork'
13
+
14
+ Spork.prefork do
15
+ # Loading more in this block will cause your specs to run faster. However,
16
+ # if you change any configuration or code from libraries loaded here, you'll
17
+ # need to restart spork for it take effect.
18
+ require File.dirname(__FILE__) + '/../config/environment.rb'
19
+ require 'spec'
20
+ require 'spec/rails'
21
+
22
+ #### this is for this test only #######
23
+ $loaded_stuff << 'prefork block' ######
24
+ #######################################
25
+ end
26
+
27
+ Spork.each_run do
28
+ # This code will be run each time you run your specs.
29
+
30
+ #### this is for this test only #######
31
+ $loaded_stuff << 'each_run block' #####
32
+ #######################################
33
+ end
34
+ """
35
+ And the application has a model, observer, route, and application helper
36
+ Scenario: Analyzing files were preloaded
37
+ When I run spork --diagnose
38
+ Then the output should not contain "user_observer.rb"
39
+ Then the output should not contain "user.rb"
40
+ Then the output should not contain "app/controllers/application.rb"
41
+ Then the output should not contain "app/controllers/application_controller.rb"
42
+ Then the output should not contain "app/controllers/application_helper.rb"
43
+ Then the output should not contain "config/routes.rb"
44
+
45
+ Scenario: Running spork with a rails app and observers
46
+ Given a file named "spec/did_it_work_spec.rb" with:
47
+ """
48
+ describe "Did it work?" do
49
+ it "checks to see if all worked" do
50
+ Spork.state.should == :using_spork
51
+ (Rails.respond_to?(:logger) ? Rails.logger : ActionController::Base.logger).info "hey there"
52
+ $loaded_stuff.should include('ActiveRecord::Base.establish_connection')
53
+ $loaded_stuff.should include('User')
54
+ $loaded_stuff.should include('UserObserver')
55
+ $loaded_stuff.should include('ApplicationHelper')
56
+ $loaded_stuff.should include('config/routes.rb')
57
+ $loaded_stuff.should include('each_run block')
58
+ $loaded_stuff.should include('prefork block')
59
+ puts "Specs successfully run within spork, and all initialization files were loaded"
60
+ end
61
+ end
62
+ """
63
+ When I fire up a spork instance with "spork rspec"
64
+ And I run spec --drb spec/did_it_work_spec.rb
65
+ Then the output should contain "Specs successfully run within spork, and all initialization files were loaded"
66
+ And the file "log/test.log" should include "hey there"
67
+
68
+
69
+ Scenario: Running spork with a rails app and a non-standard port
70
+ Given a file named "spec/did_it_work_spec.rb" with:
71
+ """
72
+ describe "Did it work?" do
73
+ it "checks to see if all worked" do
74
+ Spork.state.should == :using_spork
75
+ (Rails.respond_to?(:logger) ? Rails.logger : ActionController::Base.logger).info "hey there"
76
+ $loaded_stuff.should include('ActiveRecord::Base.establish_connection')
77
+ $loaded_stuff.should include('User')
78
+ $loaded_stuff.should include('UserObserver')
79
+ $loaded_stuff.should include('ApplicationHelper')
80
+ $loaded_stuff.should include('config/routes.rb')
81
+ $loaded_stuff.should include('each_run block')
82
+ $loaded_stuff.should include('prefork block')
83
+ puts "Specs successfully run within spork, and all initialization files were loaded"
84
+ end
85
+ end
86
+ """
87
+ When I fire up a spork instance with "spork rspec --port 7000"
88
+ And I run spec --drb --port 7000 spec/did_it_work_spec.rb
89
+ Then the output should contain "Specs successfully run within spork, and all initialization files were loaded"
90
+ And the file "log/test.log" should include "hey there"
@@ -0,0 +1,53 @@
1
+ Given /^I am in a fresh rails project named "(.+)"$/ do |folder_name|
2
+ @current_dir = SporkWorld::SANDBOX_DIR
3
+ version_argument = ENV['RAILS_VERSION'] ? "_#{ENV['RAILS_VERSION']}_" : nil
4
+ # run("#{SporkWorld::RUBY_BINARY} #{%x{which rails}.chomp} #{folder_name}")
5
+ run([SporkWorld::RUBY_BINARY, '-I', Cucumber::LIBDIR, %x{which rails}.chomp, version_argument, folder_name].compact * " ")
6
+ @current_dir = File.join(File.join(SporkWorld::SANDBOX_DIR, folder_name))
7
+ end
8
+
9
+
10
+ Given "the application has a model, observer, route, and application helper" do
11
+ Given 'a file named "app/models/user.rb" with:',
12
+ """
13
+ class User < ActiveRecord::Base
14
+ $loaded_stuff << 'User'
15
+ end
16
+ """
17
+ Given 'a file named "app/models/user_observer.rb" with:',
18
+ """
19
+ class UserObserver < ActiveRecord::Observer
20
+ $loaded_stuff << 'UserObserver'
21
+ end
22
+ """
23
+ Given 'a file named "app/helpers/application_helper.rb" with:',
24
+ """
25
+ module ApplicationHelper
26
+ $loaded_stuff << 'ApplicationHelper'
27
+ end
28
+ """
29
+ Given 'the following code appears in "config/environment.rb" after /Rails::Initializer.run/:',
30
+ """
31
+ config.active_record.observers = :user_observer
32
+ """
33
+ Given 'the following code appears in "config/routes.rb" after /^end/:',
34
+ """
35
+ $loaded_stuff << 'config/routes.rb'
36
+ """
37
+ Given 'a file named "config/initializers/initialize_loaded_stuff.rb" with:',
38
+ """
39
+ $loaded_stuff ||= []
40
+ """
41
+ Given 'a file named "config/initializers/log_establish_connection_calls.rb" with:',
42
+ """
43
+ class ActiveRecord::Base
44
+ class << self
45
+ def establish_connection_with_load_logging(*args)
46
+ establish_connection_without_load_logging(*args)
47
+ $loaded_stuff << 'ActiveRecord::Base.establish_connection'
48
+ end
49
+ alias_method_chain :establish_connection, :load_logging
50
+ end
51
+ end
52
+ """
53
+ end