timcharper-spork 0.5.0 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -8,11 +8,9 @@ Spork is Tim Harper's implementation of a Drb spec server (similar to the script
8
8
 
9
9
  Because Spork uses Kernel.fork, it only works on POSIX systems. This means Windows users are not invited to this party. Sorry :(
10
10
 
11
- Spork is still experimental, but is performing solid for us.
12
-
13
11
  == INSTALL:
14
12
 
15
- [sudo] gem install timcharper-spork --source http://gems.github.com/
13
+ [sudo] gem install spork
16
14
 
17
15
  alternatively:
18
16
 
@@ -35,23 +33,54 @@ Finally, run spork. A spec DRb server will be running!
35
33
 
36
34
  spork
37
35
 
38
- To get the TextMate RSpec bundle to use spork, go to config->advanced->shell variables, and add TM_RSPEC_OPTS=--drb.
36
+ == Diagnostic mode
37
+
38
+ 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:
39
+
40
+ spork --diagnose
41
+ (or spork -d, for short)
42
+
43
+ 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.
44
+
45
+ == Running specs over Spork
46
+
47
+ === RSpec
48
+
49
+ To get the TextMate RSpec bundle to use spork, go to config->advanced->shell variables, and add:
50
+
51
+ TM_RSPEC_OPTS=--drb.
39
52
 
40
- To run from the command line, use spec --drb spec/lib/my_spec.rb
53
+ To run from the command line, use:
41
54
 
42
- Or, you could add --drb to your spec.opts file.
55
+ spec --drb spec/lib/my_spec.rb
56
+
57
+ Or, you could add the following flag to your +spec.opts+ file.
58
+
59
+ --drb
60
+
61
+ === Cucumber
62
+
63
+ 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:
64
+
65
+ http://github.com/bmabey/cucumber/tree/drb_server
66
+
67
+ Use this as a guideline when "Sporking" your features/support/env.rb file
68
+
69
+ http://gist.github.com/123370
43
70
 
44
71
  == Some potential issues and ways to overcome them:
45
72
 
46
- === ActiveRecord reports "connection has gone away" for the first few specs
73
+ === Database connections don't work inside of Spork
47
74
 
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:
75
+ If you're using ActiveRecord and Rails, Spork will automatically reconnect to the database. However, if you're not using ActiveRecord, or if you're doing some tricky stuff with connections, you'll have to make sure your connections get re-established on each run. In your spec/spec_helper.rb file:
49
76
 
50
77
  Spork.each_run do
51
- ActiveRecord::Base.establish_connection # make sure that the db connection is ready.
78
+ # Do your connection re-establishing here
52
79
  end
53
80
 
54
- === Couldn't find formatter class Spec::Runner::Formatter::TextMateFormatter Make sure the --require option is specified *before* --format
81
+ === Couldn't find formatter class Spec::Runner::Formatter::TextMateFormatter
82
+
83
+ Make sure the --require option is specified *before* --format
55
84
 
56
85
  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:
57
86
 
@@ -65,7 +94,7 @@ On one of our projects, many of us using TextMate with spork, only one developer
65
94
 
66
95
  == Kudos to
67
96
 
68
- * Ben Mabey - help with documentation, testing, suggestions, patches, collaborated with Cucumber support.
97
+ * Ben Mabey - help with documentation, testing, suggestions, patches, and bringing Cucumber support.
69
98
  * David Chelimsky - for the fine RSpec testing framework, and the original rspec-rails spec_server implementation, which Spork has built upon.
70
99
  * Lead Media Partners - just for being an awesome place to work.
71
100
 
data/assets/bootstrap.rb CHANGED
@@ -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
 
@@ -0,0 +1,103 @@
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'] = "cucumber"
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/cucumber.rb" with:
63
+ """
64
+ # your cucumber env here
65
+ """
66
+ And a file named "config/database.yml" with:
67
+ """
68
+ cucumber:
69
+ adapter: sqlite3
70
+ database: db/cucumber.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 == 'cucumber'
78
+ $loaded_stuff.should include('ActiveRecord::Base.establish_connection')
79
+ $loaded_stuff.should include('User')
80
+ $loaded_stuff.should include('UserObserver')
81
+ $loaded_stuff.should include('ApplicationHelper')
82
+ $loaded_stuff.should include('config/routes.rb')
83
+ $loaded_stuff.should include('features/support/cucumber_rails_helper.rb')
84
+ $loaded_stuff.should include('each_run block')
85
+ $loaded_stuff.should include('prefork block')
86
+ puts "It worked!"
87
+ end
88
+ """
89
+ Scenario: Analyzing files were preloaded
90
+ When I run spork --diagnose
91
+ Then the output should not contain "user_observer.rb"
92
+ Then the output should not contain "user.rb"
93
+ Then the output should not contain "app/controllers/application.rb"
94
+ Then the output should not contain "app/controllers/application_controller.rb"
95
+ Then the output should not contain "app/controllers/application_helper.rb"
96
+ Then the output should not contain "config/routes.rb"
97
+ Then the output should not contain "features/step_definitions/cucumber_rails_steps.rb"
98
+ Then the output should not contain "features/support/cucumber_rails_helper.rb"
99
+
100
+ Scenario: Running spork with a rails app and observers
101
+ When I fire up a spork instance with "spork cucumber"
102
+ And I run cucumber --drb features/cucumber_rails.feature
103
+ Then the output should contain "It worked!"
@@ -0,0 +1,71 @@
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
+ end
66
+ end
67
+ """
68
+ When I fire up a spork instance with "spork rspec"
69
+ And I run spec --drb spec/controllers/users_controller_spec.rb
70
+ Then the output should contain "Controller stack is functioning"
71
+
@@ -0,0 +1,64 @@
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
+ $loaded_stuff.should include('ActiveRecord::Base.establish_connection')
52
+ $loaded_stuff.should include('User')
53
+ $loaded_stuff.should include('UserObserver')
54
+ $loaded_stuff.should include('ApplicationHelper')
55
+ $loaded_stuff.should include('config/routes.rb')
56
+ $loaded_stuff.should include('each_run block')
57
+ $loaded_stuff.should include('prefork block')
58
+ puts "Specs successfully run within spork, and all initialization files were loaded"
59
+ end
60
+ end
61
+ """
62
+ When I fire up a spork instance with "spork rspec"
63
+ And I run spec --drb spec/did_it_work_spec.rb
64
+ Then the output should contain "Specs successfully run within spork, and all initialization files were loaded"
@@ -1,5 +1,53 @@
1
1
  Given /^I am in a fresh rails project named "(.+)"$/ do |folder_name|
2
2
  @current_dir = SporkWorld::SANDBOX_DIR
3
- run("#{SporkWorld::RUBY_BINARY} #{%x{which rails}.chomp} #{folder_name}")
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, %x{which rails}.chomp, version_argument, folder_name].compact * " ")
4
6
  @current_dir = File.join(File.join(SporkWorld::SANDBOX_DIR, folder_name))
5
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
@@ -12,7 +12,24 @@ Given /^a file named "([^\"]*)" with:$/ do |file_name, file_content|
12
12
  create_file(file_name, file_content)
13
13
  end
14
14
 
15
- When /^I run (spork|spec)($| .*$)/ do |command, spork_opts|
15
+ # the following code appears in "config/environment.rb" after /Rails::Initializer.run/:
16
+ Given /^the following code appears in "([^\"]*)" after \/([^\\\/]*)\/:$/ do |file_name, regex, content|
17
+ # require 'ruby-debug'; Debugger.start; Debugger.start_control; debugger
18
+
19
+ regex = Regexp.new(regex)
20
+ in_current_dir do
21
+ content_lines = File.read(file_name).split("\n")
22
+ 0.upto(content_lines.length - 1) do |line_index|
23
+ if regex.match(content_lines[line_index])
24
+ content_lines.insert(line_index + 1, content)
25
+ break
26
+ end
27
+ end
28
+ File.open(file_name, 'wb') { |f| f << (content_lines * "\n") }
29
+ end
30
+ end
31
+
32
+ When /^I run (spork|spec|cucumber)($| .*$)/ do |command, spork_opts|
16
33
  if command == 'spork'
17
34
  command = SporkWorld::BINARY
18
35
  else
@@ -39,22 +56,26 @@ When /^I fire up a spork instance with "spork(.*)"$/ do |spork_opts|
39
56
  end
40
57
  end
41
58
 
42
- Then /^the output should contain$/ do |text|
43
- last_stdout.should include(text)
59
+ Then /^the (error output|output) should contain$/ do |which, text|
60
+ (which == "error output" ? last_stderr : last_stdout).should include(text)
61
+ end
62
+
63
+ Then /^the (error output|output) should contain "(.+)"$/ do |which, text|
64
+ (which == "error output" ? last_stderr : last_stdout).should include(text)
44
65
  end
45
66
 
46
- Then /^the output should contain "(.+)"$/ do |text|
47
- last_stdout.should include(text)
67
+ Then /^the (error output|output) should match \/(.+)\/$/ do |which, regex|
68
+ (which == "error output" ? last_stderr : last_stdout).should match(Regexp.new(regex))
48
69
  end
49
70
 
50
- Then /^the output should not contain$/ do |text|
51
- last_stdout.should_not include(text)
71
+ Then /^the (error output|output) should not contain$/ do |which, text|
72
+ (which == "error output" ? last_stderr : last_stdout).should_not include(text)
52
73
  end
53
74
 
54
- Then /^the output should not contain "(.+)"$/ do |text|
55
- last_stdout.should_not include(text)
75
+ Then /^the (error output|output) should not contain "(.+)"$/ do |which, text|
76
+ (which == "error output" ? last_stderr : last_stdout).should_not include(text)
56
77
  end
57
78
 
58
- Then /^the output should be$/ do |text|
59
- last_stdout.should == text
79
+ Then /^the (error output|output) should be$/ do |which, text|
80
+ (which == "error output" ? last_stderr : last_stdout).should == text
60
81
  end
@@ -53,7 +53,6 @@ class SporkWorld
53
53
  parent_stderr, child_stderr = IO::pipe
54
54
 
55
55
  background_jobs << Kernel.fork do
56
- # grandchild
57
56
  [parent_stdin, parent_stdout, parent_stderr].each { |io| io.close }
58
57
 
59
58
  STDIN.reopen(child_stdin)
@@ -0,0 +1,42 @@
1
+ Feature: Unknown app frameworks
2
+ To increase to usefulness of Spork
3
+ Spork will work with unknown (or no) application frameworks
4
+
5
+ Scenario: Unsporked spec_helper
6
+
7
+ Given a file named "spec/spec_helper.rb" with:
8
+ """
9
+ require 'rubygems'
10
+ require 'spec'
11
+ """
12
+ When I run spork
13
+ Then the error output should contain "Using RSpec"
14
+ Then the error output should match /You must bootstrap .+spec\/spec_helper\.rb to continue/
15
+
16
+ Scenario: Sporked spec_helper
17
+ Given a file named "spec/spec_helper.rb" with:
18
+ """
19
+ require 'rubygems'
20
+ require 'spork'
21
+
22
+ Spork.prefork do
23
+ require 'spec'
24
+ end
25
+
26
+ Spork.each_run do
27
+ $each_run
28
+ end
29
+ """
30
+ And a file named "spec/did_it_work_spec.rb" with:
31
+ """
32
+ describe "Did it work?" do
33
+ it "checks to see if all worked" do
34
+ Spork.state.should == :using_spork
35
+ puts "Specs successfully run within spork"
36
+ end
37
+ end
38
+ """
39
+ When I fire up a spork instance with "spork rspec"
40
+ And I run spec --drb spec/did_it_work_spec.rb
41
+ Then the output should contain "Specs successfully run within spork"
42
+
@@ -1,68 +1,82 @@
1
1
  class Spork::AppFramework::Rails < Spork::AppFramework
2
2
 
3
3
  # TODO - subclass this out to handle different versions of rails
4
- class NinjaPatcher
5
- def self.run
6
- install_hook
7
- end
8
-
9
- def self.install_hook
10
- ::Rails::Initializer.class_eval do
11
- alias :require_frameworks_without_spork :require_frameworks unless method_defined?(:require_frameworks_without_spork)
12
- def require_frameworks
13
- result = require_frameworks_without_spork
14
- Spork::AppFramework[:Rails].ninja_patcher.install_specific_hooks
15
- result
4
+ module NinjaPatcher
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ unless method_defined?(:load_environment_without_spork)
8
+ alias :load_environment_without_spork :load_environment
9
+ alias :load_environment :load_environment_with_spork
16
10
  end
17
11
  end
18
12
  end
19
13
 
20
- def self.install_specific_hooks
14
+ def load_environment_with_spork
15
+ reset_rails_env
16
+ result = load_environment_without_spork
17
+ install_hooks
18
+ result
19
+ end
20
+
21
+ def install_hooks
21
22
  auto_reestablish_db_connection
22
23
  delay_observer_loading
23
24
  delay_app_preload
24
25
  delay_application_controller_loading
26
+ delay_route_loading
25
27
  end
26
28
 
27
- def self.delay_observer_loading
28
- if Object.const_defined?(:ActiveRecord)
29
- Spork.trap_method(::ActiveRecord::Observing::ClassMethods, :instantiate_observers)
29
+ def reset_rails_env
30
+ return unless ENV['RAILS_ENV']
31
+ Object.send(:remove_const, :RAILS_ENV)
32
+ Object.const_set(:RAILS_ENV, ENV['RAILS_ENV'].dup)
33
+ end
34
+
35
+ def delay_observer_loading
36
+ if ::Rails::Initializer.instance_methods.include?('load_observers')
37
+ Spork.trap_method(::Rails::Initializer, :load_observers)
30
38
  end
31
39
  if Object.const_defined?(:ActionController)
32
40
  require "action_controller/dispatcher.rb"
33
- Spork.trap_class_method(::ActionController::Dispatcher, :define_dispatcher_callbacks)
41
+ Spork.trap_class_method(::ActionController::Dispatcher, :define_dispatcher_callbacks) if ActionController::Dispatcher.respond_to?(:define_dispatcher_callbacks)
34
42
  end
35
43
  end
36
44
 
37
- def self.delay_app_preload
45
+ def delay_app_preload
38
46
  if ::Rails::Initializer.instance_methods.include?('load_application_classes')
39
47
  Spork.trap_method(::Rails::Initializer, :load_application_classes)
40
48
  end
41
49
  end
42
50
 
43
- def self.delay_application_controller_loading
51
+ def delay_application_controller_loading
44
52
  if application_controller_source = ["#{Dir.pwd}/app/controllers/application.rb", "#{Dir.pwd}/app/controllers/application_controller.rb"].find { |f| File.exist?(f) }
45
53
  application_helper_source = "#{Dir.pwd}/app/helpers/application_helper.rb"
46
- load_paths = (Object.const_defined?(:Dependencies) ? ::Dependencies : ::ActiveSupport::Dependencies).load_paths
54
+ load_paths = (::ActiveSupport.const_defined?(:Dependencies) ? ::ActiveSupport::Dependencies : ::Dependencies).load_paths
47
55
  load_paths.unshift(File.expand_path('rails_stub_files', File.dirname(__FILE__)))
48
56
  Spork.each_run do
49
57
  require application_controller_source
50
58
  require application_helper_source if File.exist?(application_helper_source)
59
+ # update the rails magic to refresh the module
60
+ ApplicationController.send(:helper, ApplicationHelper)
51
61
  end
52
62
  end
53
63
  end
54
64
 
55
- def self.auto_reestablish_db_connection
65
+ def auto_reestablish_db_connection
56
66
  if Object.const_defined?(:ActiveRecord)
57
67
  Spork.each_run do
68
+ # rails lib/test_help.rb is very aggressive about overriding RAILS_ENV and will switch it back to test after the cucumber env was loaded
69
+ reset_rails_env
58
70
  ActiveRecord::Base.establish_connection
59
71
  end
60
72
  end
61
73
  end
62
- end
63
-
64
- def bootstrap_required?
65
- false
74
+
75
+ def delay_route_loading
76
+ if ::Rails::Initializer.instance_methods.include?('initialize_routing')
77
+ Spork.trap_method(::Rails::Initializer, :initialize_routing)
78
+ end
79
+ end
66
80
  end
67
81
 
68
82
  def preload(&block)
@@ -70,14 +84,15 @@ class Spork::AppFramework::Rails < Spork::AppFramework
70
84
  STDERR.flush
71
85
  ENV["RAILS_ENV"] ||= 'test'
72
86
  preload_rails
73
- require environment_file
74
87
  yield
75
88
  end
76
89
 
77
- def environment_file
78
- @environment_file ||= File.expand_path("config/environment.rb", Dir.pwd)
90
+ def entry_point
91
+ @entry_point ||= File.expand_path("config/environment.rb", Dir.pwd)
79
92
  end
80
93
 
94
+ alias :environment_file :entry_point
95
+
81
96
  def boot_file
82
97
  @boot_file ||= File.join(File.dirname(environment_file), 'boot')
83
98
  end
@@ -100,14 +115,10 @@ class Spork::AppFramework::Rails < Spork::AppFramework
100
115
  )
101
116
  end
102
117
 
103
- def ninja_patcher
104
- ::Spork::AppFramework::Rails::NinjaPatcher
105
- end
106
-
107
118
  def preload_rails
108
119
  Object.const_set(:RAILS_GEM_VERSION, version) if version
109
120
  require boot_file
110
- ninja_patcher.run
121
+ ::Rails::Initializer.send(:include, Spork::AppFramework::Rails::NinjaPatcher)
111
122
  end
112
123
 
113
124
  end
@@ -1,6 +1,2 @@
1
1
  class Spork::AppFramework::Unknown < Spork::AppFramework
2
- def bootstrap_required?
3
- true
4
- end
5
-
6
2
  end
@@ -33,14 +33,18 @@ class Spork::AppFramework
33
33
  end
34
34
 
35
35
  def bootstrap_required?
36
- raise NotImplemented
36
+ entry_point.nil?
37
+ end
38
+
39
+ def entry_point
40
+ nil
37
41
  end
38
42
 
39
43
  def preload(&block)
40
44
  yield
41
45
  end
42
46
 
43
- def name
47
+ def short_name
44
48
  self.class.short_name
45
49
  end
46
50
  end
@@ -4,8 +4,9 @@ class Spork::Diagnoser
4
4
  @loaded_files ||= {}
5
5
  end
6
6
 
7
- def install_hook!(dir = Dir.pwd)
7
+ def install_hook!(entry_file = nil, dir = Dir.pwd)
8
8
  @dir = File.expand_path(Dir.pwd, dir)
9
+ @entry_file = entry_file
9
10
 
10
11
  Kernel.class_eval do
11
12
  alias :require_without_diagnoser :require
@@ -26,21 +27,7 @@ class Spork::Diagnoser
26
27
  def add_included_file(filename, callstack)
27
28
  filename = expand_filename(filename)
28
29
  return unless File.exist?(filename)
29
- loaded_files[filename] = caller.select { |f| ! f.include?('lib/spork/diagnoser.rb')} if subdirectory?(filename)
30
- end
31
-
32
- def expand_filename(filename)
33
- ([Dir.pwd] + $:).each do |attempted_path|
34
- attempted_filename = File.expand_path(filename, attempted_path)
35
- return attempted_filename if File.file?(attempted_filename)
36
- attempted_filename = attempted_filename + ".rb"
37
- return attempted_filename if File.file?(attempted_filename)
38
- end
39
- filename
40
- end
41
-
42
- def subdirectory?(directory)
43
- File.expand_path(directory, Dir.pwd).include?(@dir)
30
+ loaded_files[filename] = filter_callstack(caller) if subdirectory?(filename)
44
31
  end
45
32
 
46
33
  def remove_hook!
@@ -68,5 +55,29 @@ class Spork::Diagnoser
68
55
  stdout.puts loaded_files[file].map(&minimify)
69
56
  end
70
57
  end
58
+
59
+ private
60
+ def filter_callstack(callstack, entry_file = @entry_file)
61
+ callstack.pop until callstack.empty? || callstack.last.include?(@entry_file) if @entry_file
62
+ callstack.map do |line|
63
+ next if line.include?('lib/spork/diagnoser.rb')
64
+ line.gsub!('require_without_diagnoser', 'require')
65
+ line
66
+ end.compact
67
+ end
68
+
69
+ def expand_filename(filename)
70
+ ([Dir.pwd] + $:).each do |attempted_path|
71
+ attempted_filename = File.expand_path(filename, attempted_path)
72
+ return attempted_filename if File.file?(attempted_filename)
73
+ attempted_filename = attempted_filename + ".rb"
74
+ return attempted_filename if File.file?(attempted_filename)
75
+ end
76
+ filename
77
+ end
78
+
79
+ def subdirectory?(directory)
80
+ File.expand_path(directory, Dir.pwd).include?(@dir)
81
+ end
71
82
  end
72
83
  end
data/lib/spork/runner.rb CHANGED
@@ -85,7 +85,7 @@ Are you running me from a project directory?
85
85
  when options[:diagnose]
86
86
  require 'spork/diagnoser'
87
87
 
88
- Spork::Diagnoser.install_hook!
88
+ Spork::Diagnoser.install_hook!(server.entry_point)
89
89
  server.preload
90
90
  Spork::Diagnoser.output_results(@output)
91
91
  return true
data/lib/spork/server.rb CHANGED
@@ -94,7 +94,7 @@ class Spork::Server
94
94
  end
95
95
 
96
96
  def run(argv, stderr, stdout)
97
- return false if running?
97
+ abort if running?
98
98
 
99
99
  @child = ::Spork::Forker.new do
100
100
  $stdout, $stderr = stdout, stderr
@@ -113,6 +113,10 @@ class Spork::Server
113
113
  @framework ||= Spork::AppFramework.detect_framework
114
114
  end
115
115
 
116
+ def self.entry_point
117
+ bootstrapped? ? helper_file : framework.entry_point
118
+ end
119
+
116
120
  def self.preload
117
121
  Spork.exec_prefork do
118
122
  unless bootstrapped?
@@ -123,6 +127,8 @@ class Spork::Server
123
127
  stderr.puts "I can't do anything for you by default for the framework your using: #{framework.short_name}.\nYou must bootstrap #{helper_file} to continue."
124
128
  stderr.flush
125
129
  return false
130
+ else
131
+ load(framework.entry_point)
126
132
  end
127
133
  end
128
134
 
data/lib/spork.rb CHANGED
@@ -51,7 +51,7 @@ module Spork
51
51
  def expanded_caller(caller_line)
52
52
  file, line = caller_line.split(":")
53
53
  line.gsub(/:.+/, '')
54
- File.expand_path(Dir.pwd, file) + ":" + line
54
+ File.expand_path(file, Dir.pwd) + ":" + line
55
55
  end
56
56
 
57
57
  def trap_method(klass, method_name)
data/spec/spec_helper.rb CHANGED
@@ -18,6 +18,7 @@ unless $spec_helper_loaded
18
18
  config.before(:each) do
19
19
  $test_stdout = StringIO.new
20
20
  $test_stderr = StringIO.new
21
+ @current_dir = nil
21
22
  end
22
23
 
23
24
  config.after(:each) do
@@ -41,6 +42,10 @@ unless $spec_helper_loaded
41
42
  def current_dir
42
43
  @current_dir ||= SPEC_TMP_DIR
43
44
  end
45
+
46
+ def change_current_dir(sub_path)
47
+ @current_dir = File.expand_path(sub_path, SPEC_TMP_DIR)
48
+ end
44
49
  end
45
50
 
46
51
 
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ Spork::AppFramework[:Unknown]
4
+
5
+ describe Spork::AppFramework::Unknown do
6
+ it "requires bootstrapping" do
7
+ Spork::AppFramework::Unknown.new.bootstrap_required?.should == true
8
+ end
9
+
10
+ it "has no known entry point" do
11
+ Spork::AppFramework::Unknown.new.entry_point.should be_nil
12
+ end
13
+ end
14
+
@@ -5,12 +5,12 @@ describe Spork::AppFramework do
5
5
  it "detects when rails is installed and available" do
6
6
  create_file("config/environment.rb", "RAILS_GEM_VERSION = '2.1.0'")
7
7
  in_current_dir do
8
- Spork::AppFramework.detect_framework.name.should == "Rails"
8
+ Spork::AppFramework.detect_framework.short_name.should == "Rails"
9
9
  end
10
10
  end
11
11
 
12
12
  it "returns Unknown when no framework known detected" do
13
- Spork::AppFramework.detect_framework.name.should == "Unknown"
13
+ Spork::AppFramework.detect_framework.short_name.should == "Unknown"
14
14
  end
15
15
  end
16
16
  end
@@ -22,13 +22,11 @@ describe Spork::Diagnoser do
22
22
  it "installs it's hook and tells you when files have been loaded" do
23
23
  run_simulation(SPEC_TMP_DIR, 'my_awesome_library_include.rb', '1 + 5')
24
24
  Spork::Diagnoser.loaded_files.keys.should include_a_string_like('my_awesome_library_include')
25
-
26
25
  end
27
-
26
+
28
27
  it 'excludes files outside of Dir.pwd' do
29
28
  run_simulation(SPEC_TMP_DIR + '/project_root', '../external_dependency.rb', '1 + 5')
30
29
  Spork::Diagnoser.loaded_files.keys.should_not include_a_string_like('external_dependency')
31
-
32
30
  end
33
31
 
34
32
  it "excludes files outside of Dir.pwd but in ruby's include path" do
@@ -79,13 +77,29 @@ describe Spork::Diagnoser do
79
77
  $:.pop
80
78
  end
81
79
 
82
- it "outputs the results relative to the current directory" do
83
- Spork::Diagnoser.loaded_files["/project_path/lib/file.rb"] = "/project_path/lib/parent_file.rb:35"
84
- Dir.stub!(:pwd).and_return("/project_path")
85
- out = StringIO.new
86
- Spork::Diagnoser.output_results(out)
87
- out.string.should =~ %r([^/]lib/file.rb)
88
- out.string.should =~ %r([^/]lib/parent_file.rb)
89
- out.string.should_not include("/project_path/")
80
+ it "filters backtrace beyond the last line matching the entry point" do
81
+ Spork::Diagnoser.install_hook!("test_filter/environment.rb")
82
+ create_file("test_filter/environment.rb", "require 'test_filter/app.rb'")
83
+ create_file("test_filter/app.rb", "require 'test_filter/my_model.rb'")
84
+ create_file("test_filter/my_model.rb", "'my model here'")
85
+ in_current_dir do
86
+ require 'test_filter/environment.rb'
87
+ end
88
+ f = Spork::Diagnoser.loaded_files
89
+ f[f.keys.grep(/app.rb/).first].last.should include('test_filter/environment.rb')
90
+ f[f.keys.grep(/my_model.rb/).first].last.should include('test_filter/environment.rb')
91
+ f[f.keys.grep(/environment.rb/).first].should == []
92
+ end
93
+
94
+ describe ".output_results" do
95
+ it "outputs the results relative to the current directory" do
96
+ Spork::Diagnoser.loaded_files["/project_path/lib/file.rb"] = "/project_path/lib/parent_file.rb:35"
97
+ Dir.stub!(:pwd).and_return("/project_path")
98
+ out = StringIO.new
99
+ Spork::Diagnoser.output_results(out)
100
+ out.string.should =~ %r([^/]lib/file.rb)
101
+ out.string.should =~ %r([^/]lib/parent_file.rb)
102
+ out.string.should_not include("/project_path/")
103
+ end
90
104
  end
91
105
  end
data/spec/spork_spec.rb CHANGED
@@ -55,4 +55,8 @@ describe Spork do
55
55
  Spork.each_run { }
56
56
  spec_helper_simulator.should == [:prefork, :each_run]
57
57
  end
58
+
59
+ it "expands a caller line, preserving the line number" do
60
+ Spork.expanded_caller("/boo/../yah.rb:31").should == "/yah.rb:31"
61
+ end
58
62
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timcharper-spork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Harper
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-05 00:00:00 -07:00
12
+ date: 2009-06-10 00:00:00 -07:00
13
13
  default_executable: spork
14
14
  dependencies: []
15
15
 
@@ -27,11 +27,14 @@ files:
27
27
  - MIT-LICENSE
28
28
  - README.rdoc
29
29
  - assets/bootstrap.rb
30
+ - features/cucumber_rails_integration.feature
30
31
  - features/diagnostic_mode.feature
31
- - features/rails_integration.feature
32
+ - features/rails_delayed_loading_workarounds.feature
33
+ - features/rspec_rails_integration.feature
32
34
  - features/steps/rails_steps.rb
33
35
  - features/steps/sandbox_steps.rb
34
36
  - features/support/env.rb
37
+ - features/unknown_app_framework.feature
35
38
  - lib/spork.rb
36
39
  - lib/spork/app_framework.rb
37
40
  - lib/spork/app_framework/rails.rb
@@ -48,6 +51,7 @@ files:
48
51
  - lib/spork/server/rspec.rb
49
52
  - spec/spec_helper.rb
50
53
  - spec/spork/app_framework/rails_spec.rb
54
+ - spec/spork/app_framework/unknown_spec.rb
51
55
  - spec/spork/app_framework_spec.rb
52
56
  - spec/spork/diagnoser_spec.rb
53
57
  - spec/spork/forker_spec.rb
@@ -85,6 +89,7 @@ summary: spork
85
89
  test_files:
86
90
  - spec/spec_helper.rb
87
91
  - spec/spork/app_framework/rails_spec.rb
92
+ - spec/spork/app_framework/unknown_spec.rb
88
93
  - spec/spork/app_framework_spec.rb
89
94
  - spec/spork/diagnoser_spec.rb
90
95
  - spec/spork/forker_spec.rb
@@ -1,77 +0,0 @@
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
- require 'spec'
14
-
15
- Spork.prefork do
16
- $run_phase = :prefork
17
- require File.dirname(__FILE__) + '/../config/environment.rb'
18
- end
19
-
20
- Spork.each_run do
21
- $run_phase = :each_run
22
- puts "I'm loading the stuff just for this run..."
23
- end
24
-
25
- class ActiveRecord::Base
26
- class << self
27
- def establish_connection
28
- ($loaded_stuff ||= []) << 'establish_connection'
29
- puts "Database connection was automatically re-established!"
30
- end
31
- end
32
- end
33
- """
34
- And a file named "app/models/user.rb" with:
35
- """
36
- class User < ActiveRecord::Base
37
- ($loaded_stuff ||= []) << 'User'
38
- end
39
- """
40
- And a file named "app/helpers/application_helper.rb" with:
41
- """
42
- module ApplicationHelper
43
- ($loaded_stuff ||= []) << 'ApplicationHelper'
44
- end
45
- """
46
- And a file named "app/models/user_observer.rb" with:
47
- """
48
- class UserObserver < ActiveRecord::Observer
49
- ($loaded_stuff ||= []) << 'UserObserver'
50
- end
51
- """
52
- And a file named "spec/models/user_spec.rb" with:
53
- """
54
- describe User do
55
- it "does absoluately nothing" do
56
- Spork.state.should == :using_spork
57
- $loaded_stuff.should include('establish_connection')
58
- $loaded_stuff.should include('User')
59
- $loaded_stuff.should include('UserObserver')
60
- $loaded_stuff.should include('ApplicationHelper')
61
- puts "Specs successfully run within spork, and all initialization files were loaded"
62
- end
63
- end
64
- """
65
- Scenario: Analyzing files were preloaded
66
- When I run spork --diagnose
67
- Then the output should not contain "user_observer.rb"
68
- Then the output should not contain "user.rb"
69
- Then the output should not contain "app/controllers/application.rb"
70
- Then the output should not contain "app/controllers/application_controller.rb"
71
- Then the output should not contain "app/controllers/application_helper.rb"
72
-
73
- Scenario: Running spork with a rails app and observers
74
-
75
- When I fire up a spork instance with "spork rspec"
76
- And I run spec --drb spec/models/user_spec.rb
77
- Then the output should contain "Specs successfully run within spork, and all initialization files were loaded"