spork 0.5.6 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,10 @@
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
 
@@ -62,10 +62,19 @@ Feature: Rails Delayed Work arounds
62
62
  get :index
63
63
  response.body.should include('listing users')
64
64
  puts "Controller stack is functioning"
65
+ response.body.should include('Here is a list of users')
66
+ puts "Views are not being cached"
65
67
  end
66
68
  end
67
69
  """
68
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
+
69
77
  And I run spec --drb spec/controllers/users_controller_spec.rb
70
78
  Then the output should contain "Controller stack is functioning"
79
+ Then the output should contain "Views are not being cached"
71
80
 
@@ -12,6 +12,10 @@ 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 /^the contents of "([^\"]*)" are changed to:$/ do |file_name, file_content|
16
+ create_file(file_name, file_content)
17
+ end
18
+
15
19
  # the following code appears in "config/environment.rb" after /Rails::Initializer.run/:
16
20
  Given /^the following code appears in "([^\"]*)" after \/([^\\\/]*)\/:$/ do |file_name, regex, content|
17
21
  # require 'ruby-debug'; Debugger.start; Debugger.start_control; debugger
@@ -1,21 +1,23 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
2
2
  module Spork
3
3
  class << self
4
- def already_ran
5
- @already_ran ||= []
6
- end
7
-
8
- def each_run_procs
9
- @each_run_procs ||= []
10
- end
11
-
12
- def prefork(&block)
13
- return if already_ran?(caller.first)
4
+ # Run a block, during prefork mode. By default, if prefork is called twice in the same file and line number, the supplied block will only be ran once.
5
+ #
6
+ # == Parameters
7
+ #
8
+ # * +prevent_double_run+ - Pass false to disable double run prevention
9
+ def prefork(prevent_double_run = true, &block)
10
+ return if prevent_double_run && already_ran?(caller.first)
14
11
  yield
15
12
  end
16
13
 
17
- def each_run(&block)
18
- return if already_ran?(caller.first)
14
+ # Run a block AFTER the fork occurs. By default, if prefork is called twice in the same file and line number, the supplied block will only be ran once.
15
+ #
16
+ # == Parameters
17
+ #
18
+ # * +prevent_double_run+ - Pass false to disable double run prevention
19
+ def each_run(prevent_double_run = true, &block)
20
+ return if prevent_double_run && already_ran?(caller.first)
19
21
  if @state == :using_spork
20
22
  each_run_procs << block
21
23
  else
@@ -23,59 +25,72 @@ module Spork
23
25
  end
24
26
  end
25
27
 
26
- def already_ran?(caller_script_and_line)
27
- return true if already_ran.include?(expanded_caller(caller_script_and_line))
28
- already_ran << expanded_caller(caller_script_and_line)
29
- false
30
- end
31
-
28
+ # Used by the server. Sets the state to activate spork. Otherwise, prefork and each_run are run in passive mode, allowing specs without a Spork server.
32
29
  def using_spork!
33
30
  @state = :using_spork
34
31
  end
35
32
 
33
+ # Used by the server. Returns the current state of Spork.
36
34
  def state
37
35
  @state ||= :not_using_spork
38
36
  end
39
37
 
38
+ # Used by the server. Called when loading the prefork blocks of the code.
40
39
  def exec_prefork(&block)
41
40
  using_spork!
42
41
  yield
43
42
  end
44
43
 
44
+ # Used by the server. Called to run all of the prefork blocks.
45
45
  def exec_each_run(&block)
46
46
  each_run_procs.each { |p| p.call }
47
47
  each_run_procs.clear
48
48
  yield if block_given?
49
49
  end
50
50
 
51
- def expanded_caller(caller_line)
52
- file, line = caller_line.split(":")
53
- line.gsub(/:.+/, '')
54
- File.expand_path(file, Dir.pwd) + ":" + line
55
- end
56
-
51
+ # Traps an instance method of a class (or module) so any calls to it don't actually run until Spork.exec_each_run
57
52
  def trap_method(klass, method_name)
53
+ method_name_without_spork, method_name_with_spork = alias_method_names(method_name, :spork)
54
+
58
55
  klass.class_eval <<-EOF, __FILE__, __LINE__ + 1
59
- alias :#{method_name}_without_spork :#{method_name} unless method_defined?(:#{method_name}_without_spork)
56
+ alias :#{method_name_without_spork} :#{method_name} unless method_defined?(:#{method_name_without_spork})
60
57
  def #{method_name}(*args)
61
- Spork.each_run_procs << lambda do
62
- #{method_name}_without_spork(*args)
58
+ Spork.each_run(false) do
59
+ #{method_name_without_spork}(*args)
63
60
  end
64
61
  end
65
62
  EOF
66
63
  end
67
64
 
65
+ # Same as trap_method, but for class methods instead
68
66
  def trap_class_method(klass, method_name)
69
- klass.class_eval <<-EOF, __FILE__, __LINE__ + 1
70
- class << self
71
- alias :#{method_name}_without_spork :#{method_name} unless method_defined?(:#{method_name}_without_spork)
72
- def #{method_name}(*args)
73
- Spork.each_run_procs << lambda do
74
- #{method_name}_without_spork(*args)
75
- end
76
- end
77
- end
78
- EOF
67
+ trap_method((class << klass; self; end), method_name)
79
68
  end
69
+
70
+ private
71
+ def alias_method_names(method_name, feature)
72
+ /^(.+?)([\?\!]{0,1})$/.match(method_name.to_s)
73
+ ["#{$1}_without_spork#{$2}", "#{$1}_with_spork#{$2}"]
74
+ end
75
+
76
+ def already_ran
77
+ @already_ran ||= []
78
+ end
79
+
80
+ def expanded_caller(caller_line)
81
+ file, line = caller_line.split(":")
82
+ line.gsub(/:.+/, '')
83
+ File.expand_path(file, Dir.pwd) + ":" + line
84
+ end
85
+
86
+ def already_ran?(caller_script_and_line)
87
+ return true if already_ran.include?(expanded_caller(caller_script_and_line))
88
+ already_ran << expanded_caller(caller_script_and_line)
89
+ false
90
+ end
91
+
92
+ def each_run_procs
93
+ @each_run_procs ||= []
94
+ end
80
95
  end
81
96
  end
@@ -1,10 +1,22 @@
1
1
  class Spork::AppFramework
2
+ # A hash of procs where the key is the class name, and the proc takes no arguments and returns true if it detects that said application framework is being used in the project.
3
+ #
4
+ # The key :Rails maps to Spork::AppFramework::Rails
5
+ #
6
+ # This is used to reduce the amount of code needed to be loaded - only the detected application framework's support code is loaded.
2
7
  SUPPORTED_FRAMEWORKS = {
3
- :Rails => lambda do
8
+ :Rails => lambda {
4
9
  File.exist?("config/environment.rb") && File.read("config/environment.rb").include?('RAILS_GEM_VERSION')
5
- end
10
+ }
6
11
  }
7
12
 
13
+ def self.setup_autoload
14
+ ([:Unknown] + SUPPORTED_FRAMEWORKS.keys).each do |name|
15
+ autoload name, File.join(File.dirname(__FILE__), "app_framework", name.to_s.downcase)
16
+ end
17
+ end
18
+
19
+ # Iterates through all SUPPORTED_FRAMEWORKS and returns the symbolic name of the project application framework detected. Otherwise, returns :Unknown
8
20
  def self.detect_framework_name
9
21
  SUPPORTED_FRAMEWORKS.each do |key, value|
10
22
  return key if value.call
@@ -12,32 +24,37 @@ class Spork::AppFramework
12
24
  :Unknown
13
25
  end
14
26
 
27
+ # Same as detect_framework_name, but returns an instance of the specific AppFramework class.
15
28
  def self.detect_framework
16
29
  name = detect_framework_name
17
30
  self[name]
18
31
  end
19
32
 
33
+ # Initializes, stores, and returns a singleton instance of the named AppFramework.
34
+ #
35
+ # == Parameters
36
+ #
37
+ # # +name+ - A symbolic name of a AppFramework subclass
38
+ #
39
+ # == Example
40
+ #
41
+ # Spork::AppFramework[:Rails]
20
42
  def self.[](name)
21
- instances[name] ||= (
22
- require File.join(File.dirname(__FILE__), "app_framework", name.to_s.downcase)
23
- const_get(name).new
24
- )
25
- end
26
-
27
- def self.instances
28
- @instances ||= {}
43
+ instances[name] ||= const_get(name).new
29
44
  end
30
45
 
31
46
  def self.short_name
32
47
  name.gsub('Spork::AppFramework::', '')
33
48
  end
34
49
 
50
+ # If there is some stuff out of the box that the Spork can do to speed up tests without the test helper file being bootstrapped, this should return false.
35
51
  def bootstrap_required?
36
52
  entry_point.nil?
37
53
  end
38
54
 
55
+ # Abstract: The path to the file that loads the project environment, ie config/environment.rb. Returns nil if there is none.
39
56
  def entry_point
40
- nil
57
+ raise NotImplemented
41
58
  end
42
59
 
43
60
  def preload(&block)
@@ -47,4 +64,11 @@ class Spork::AppFramework
47
64
  def short_name
48
65
  self.class.short_name
49
66
  end
50
- end
67
+
68
+ protected
69
+ def self.instances
70
+ @instances ||= {}
71
+ end
72
+ end
73
+
74
+ Spork::AppFramework.setup_autoload
@@ -39,6 +39,7 @@ class Spork::AppFramework::Rails < Spork::AppFramework
39
39
  delay_app_preload
40
40
  delay_application_controller_loading
41
41
  delay_route_loading
42
+ delay_eager_view_loading
42
43
  end
43
44
 
44
45
  def reset_rails_env
@@ -92,6 +93,24 @@ class Spork::AppFramework::Rails < Spork::AppFramework
92
93
  Spork.trap_method(::Rails::Initializer, :initialize_routing)
93
94
  end
94
95
  end
96
+
97
+ def delay_eager_view_loading
98
+ # So, in testing mode it seems it would be optimal to not eager load
99
+ # views (as your may only run a test that uses one or two views).
100
+ # However, I decided to delay eager loading rather than force it to
101
+ # disable because you may wish to eager load your views (I.E. you're
102
+ # testing concurrency)
103
+
104
+ # Rails 2.3.x +
105
+ if defined?(::ActionView::Template::EagerPath)
106
+ Spork.trap_method(::ActionView::Template::EagerPath, :load!)
107
+ end
108
+ # Rails 2.2.x
109
+ if defined?(::ActionView::PathSet::Path)
110
+ Spork.trap_method(::ActionView::PathSet::Path, :load)
111
+ end
112
+ # Rails 2.0.5 - 2.1.x don't appear to eager cache views.
113
+ end
95
114
  end
96
115
 
97
116
  def preload(&block)
@@ -1,2 +1,3 @@
1
+ # This is a stub used to help Spork delay the loading of the real ApplicationController
1
2
  class ::ApplicationController < ActionController::Base
2
3
  end
@@ -1,2 +1,3 @@
1
+ # This is a stub used to help Spork delay the loading of the real ApplicationController
1
2
  class ::ApplicationController < ActionController::Base
2
3
  end
@@ -1,2 +1,3 @@
1
+ # This is a stub used to help Spork delay the loading of the real ApplicationHelper
1
2
  module ::ApplicationHelper
2
3
  end
@@ -1,2 +1,6 @@
1
+ # This is used if no supported appliction framework is detected
1
2
  class Spork::AppFramework::Unknown < Spork::AppFramework
3
+ def entry_point
4
+ nil
5
+ end
2
6
  end
@@ -1,3 +1,5 @@
1
+ # This class is mainly used for testing.
2
+ # When included (and used), it gives us an opportunity to stub out the output streams used for a given class
1
3
  module Spork::CustomIOStreams
2
4
  def self.included(klass)
3
5
  klass.send(:extend, ::Spork::CustomIOStreams::ClassMethods)
@@ -1,9 +1,23 @@
1
+ # The Diagnoser hooks into load and require and keeps track of when files are required / loaded, and who loaded them.
2
+ # It's used when you run spork --diagnose
3
+ #
4
+ # = Example
5
+ #
6
+ # Spork::Diagnoser.install_hook!('/path/env.rb', '/path')
7
+ # require '/path/to/env.rb'
8
+ # Spork::Diagnoser.output_results(STDOUT)
1
9
  class Spork::Diagnoser
2
10
  class << self
3
11
  def loaded_files
4
12
  @loaded_files ||= {}
5
13
  end
6
14
 
15
+ # Installs the diagnoser hook into Kernel#require and Kernel#load
16
+ #
17
+ # == Parameters
18
+ #
19
+ # * +entry_file+ - The file that is used to load the project. Used to filter the backtrace so anything that happens after it is hidden.
20
+ # * +dir+ - The project directory. Any file loaded outside of this directory will not be logged.
7
21
  def install_hook!(entry_file = nil, dir = Dir.pwd)
8
22
  @dir = File.expand_path(Dir.pwd, dir)
9
23
  @entry_file = entry_file
@@ -30,6 +44,7 @@ class Spork::Diagnoser
30
44
  loaded_files[filename] = filter_callstack(caller) if subdirectory?(filename)
31
45
  end
32
46
 
47
+ # Uninstall the hook. Generally useful only for testing the Diagnoser.
33
48
  def remove_hook!
34
49
  return unless Kernel.private_instance_methods.include?('require_without_diagnoser')
35
50
  Kernel.class_eval do
@@ -42,6 +57,11 @@ class Spork::Diagnoser
42
57
  true
43
58
  end
44
59
 
60
+ # output the results of a diagnostic run.
61
+ #
62
+ # == Parameters
63
+ #
64
+ # * +stdout+ - An IO stream to output the results to.
45
65
  def output_results(stdout)
46
66
  project_prefix = Dir.pwd + "/"
47
67
  minimify = lambda { |f| f.gsub(project_prefix, '')}
@@ -1,4 +1,16 @@
1
+ # A helper class that allows you to run a block inside of a fork, and then get the result from that block.
2
+ #
3
+ # == Example:
4
+ #
5
+ # forker = Spork::Forker.new do
6
+ # sleep 3
7
+ # "success"
8
+ # end
9
+ #
10
+ # forker.result # => "success"
1
11
  class Spork::Forker
12
+
13
+ # Raised if the fork died (was killed) before it sent it's response back.
2
14
  class ForkDiedException < Exception; end
3
15
  def initialize(&block)
4
16
  return unless block_given?
@@ -20,6 +32,9 @@ class Spork::Forker
20
32
  @child_io.close
21
33
  end
22
34
 
35
+ # Wait for the fork to finish running, and then return its return value.
36
+ #
37
+ # If the fork was aborted, then result returns nil.
23
38
  def result
24
39
  return unless running?
25
40
  result_thread = Thread.new do
@@ -36,6 +51,7 @@ class Spork::Forker
36
51
  @result
37
52
  end
38
53
 
54
+ # abort the current running fork
39
55
  def abort
40
56
  if running?
41
57
  Process.kill(Signal.list['TERM'], @child_pid)
@@ -2,6 +2,7 @@ require 'optparse'
2
2
  require 'spork/server'
3
3
 
4
4
  module Spork
5
+ # This is used by bin/spork. It's wrapped in a class because it's easier to test that way.
5
6
  class Runner
6
7
  attr_reader :server
7
8
 
@@ -42,6 +43,7 @@ module Spork
42
43
  text.string
43
44
  end
44
45
 
46
+ # Returns a server for the specified (or the detected default) testing framework. Returns nil if none detected, or if the specified is not supported or available.
45
47
  def find_server
46
48
  if options[:server_matcher]
47
49
  @server = Spork::Server.supported_servers(options[:server_matcher]).first
@@ -96,9 +98,6 @@ Are you running me from a project directory?
96
98
  end
97
99
  end
98
100
 
99
- def diagnose
100
- end
101
-
102
101
  private
103
102
  attr_reader :options
104
103
 
@@ -4,7 +4,9 @@ require 'spork/forker.rb'
4
4
  require 'spork/custom_io_streams.rb'
5
5
  require 'spork/app_framework.rb'
6
6
 
7
- # This is based off of spec_server.rb from rspec-rails (David Chelimsky), which was based on Florian Weber's TDDMate
7
+ # An abstract class that is implemented to create a server
8
+ #
9
+ # (This was originally based off of spec_server.rb from rspec-rails (David Chelimsky), which was based on Florian Weber's TDDMate)
8
10
  class Spork::Server
9
11
  @@supported_servers = []
10
12
 
@@ -13,26 +15,27 @@ class Spork::Server
13
15
 
14
16
  include Spork::CustomIOStreams
15
17
 
18
+ # Abstract method: returns the servers port. Override this to return the port that should be used by the test framework.
16
19
  def self.port
17
20
  raise NotImplemented
18
21
  end
19
22
 
23
+ # Abstract method: returns the entry file that loads the testing environment, such as spec/spec_helper.rb.
20
24
  def self.helper_file
21
25
  raise NotImplemented
22
26
  end
23
27
 
28
+ # Convenience method that turns the class name without the namespace
24
29
  def self.server_name
25
30
  self.name.gsub('Spork::Server::', '')
26
31
  end
27
32
 
28
- def self.inherited(subclass)
29
- @@supported_servers << subclass
30
- end
31
-
33
+ # Returns a list of all testing servers that have detected their testing framework being used in the project.
32
34
  def self.available_servers
33
35
  supported_servers.select { |s| s.available? }
34
36
  end
35
37
 
38
+ # Returns a list of all servers that have been implemented (it keeps track of them automatically via Class.inherited)
36
39
  def self.supported_servers(starting_with = nil)
37
40
  @@supported_servers.sort! { |a,b| a.load_preference_index <=> b.load_preference_index }
38
41
  return @@supported_servers if starting_with.nil?
@@ -41,18 +44,22 @@ class Spork::Server
41
44
  end
42
45
  end
43
46
 
47
+ # Returns true if the testing frameworks helper file exists. Override if this is not sufficient to detect your testing framework.
44
48
  def self.available?
45
49
  File.exist?(helper_file)
46
50
  end
47
51
 
52
+ # Used to specify
48
53
  def self.load_preference_index
49
54
  LOAD_PREFERENCE.index(server_name) || LOAD_PREFERENCE.length
50
55
  end
51
56
 
57
+ # Detects if the test helper has been bootstrapped.
52
58
  def self.bootstrapped?
53
59
  File.read(helper_file).include?("Spork.prefork")
54
60
  end
55
61
 
62
+ # Bootstraps the current test helper file by prepending a Spork.prefork and Spork.each_run block at the beginning.
56
63
  def self.bootstrap
57
64
  if bootstrapped?
58
65
  stderr.puts "Already bootstrapped!"
@@ -75,6 +82,7 @@ class Spork::Server
75
82
  new.listen
76
83
  end
77
84
 
85
+ # Sets up signals and starts the DRb service. If it's successful, it doesn't return. Not ever. You don't need to override this.
78
86
  def listen
79
87
  trap("SIGINT") { sig_int_received }
80
88
  trap("SIGTERM") { abort; exit!(0) }
@@ -93,6 +101,14 @@ class Spork::Server
93
101
  self.class.helper_file
94
102
  end
95
103
 
104
+ # This is the public facing method that is served up by DRb. To use it from the client side (in a testing framework):
105
+ #
106
+ # DRb.start_service("druby://localhost:0") # this allows Ruby to do some magical stuff so you can pass an output stream over DRb.
107
+ # # see http://redmine.ruby-lang.org/issues/show/496 to see why localhost:0 is used.
108
+ # spec_server = DRbObject.new_with_uri("druby://127.0.0.1:8989")
109
+ # spec_server.run(options.argv, $stderr, $stdout)
110
+ #
111
+ # When implementing a test server, don't override this method: override run_tests instead.
96
112
  def run(argv, stderr, stdout)
97
113
  abort if running?
98
114
 
@@ -104,11 +120,22 @@ class Spork::Server
104
120
  @child.result
105
121
  end
106
122
 
123
+ # returns whether or not the child (a test run) is running right now.
107
124
  def running?
108
125
  @child && @child.running?
109
126
  end
110
127
 
128
+ protected
129
+ # Abstract method: here is where the server runs the tests.
130
+ def run_tests(argv, input, output)
131
+ raise NotImplemented
132
+ end
133
+
111
134
  private
135
+ def self.inherited(subclass)
136
+ @@supported_servers << subclass
137
+ end
138
+
112
139
  def self.framework
113
140
  @framework ||= Spork::AppFramework.detect_framework
114
141
  end
@@ -143,10 +170,6 @@ class Spork::Server
143
170
  true
144
171
  end
145
172
 
146
- def run_tests(argv, input, output)
147
- raise NotImplemented
148
- end
149
-
150
173
  def restart
151
174
  stderr.puts "restarting"
152
175
  stderr.flush
@@ -1,7 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
- Spork::AppFramework[:Rails]
4
-
5
3
  describe Spork::AppFramework::Rails do
6
4
  describe ".version" do
7
5
  it "detects the current version of rails" do
@@ -1,7 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
- Spork::AppFramework[:Unknown]
4
-
5
3
  describe Spork::AppFramework::Unknown do
6
4
  it "requires bootstrapping" do
7
5
  Spork::AppFramework::Unknown.new.bootstrap_required?.should == true
@@ -1,36 +1,44 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
3
  describe Spork::Forker do
4
- it "runs a block in a fork" do
5
- @var = "hello world"
6
- Spork::Forker.new { @var = "booyah" }.result
7
- @var.should == "hello world"
4
+ describe ".new" do
5
+ it "runs a block in a fork" do
6
+ $var = "hello world"
7
+ Spork::Forker.new { $var = "booyah" }.result
8
+ $var.should == "hello world"
9
+ end
8
10
  end
9
11
 
10
- it "returns the result" do
11
- Spork::Forker.new { "results" }.result.should == "results"
12
+ describe "#result" do
13
+ it "returns the result" do
14
+ Spork::Forker.new { "results" }.result.should == "results"
15
+ end
12
16
  end
13
17
 
14
- it "reports when the fork is running" do
15
- forker = Spork::Forker.new { sleep 0.1 }
16
- forker.running?.should == true
17
- forker.result
18
- sleep 0.1
19
- forker.running?.should == false
18
+ describe "#running?" do
19
+ it "reports when the fork is running" do
20
+ forker = Spork::Forker.new { sleep 0.1 }
21
+ forker.running?.should == true
22
+ forker.result
23
+ sleep 0.1
24
+ forker.running?.should == false
25
+ end
20
26
  end
21
27
 
22
- it "aborts a fork and returns nil for the result" do
23
- started_at = Time.now
24
- ended_at = nil
25
- forker = Spork::Forker.new { sleep 5 }
26
- Thread.new do
27
- forker.result.should == nil
28
- ended_at = Time.now
28
+ describe "#abort" do
29
+ it "aborts a fork and returns nil for the result" do
30
+ started_at = Time.now
31
+ ended_at = nil
32
+ forker = Spork::Forker.new { sleep 5 }
33
+ Thread.new do
34
+ forker.result.should == nil
35
+ ended_at = Time.now
36
+ end
37
+ sleep 0.5
38
+ forker.abort
39
+ sleep 0.1
40
+ (ended_at - started_at).should be_close(0.5, 0.1)
41
+ forker.running?.should == false
29
42
  end
30
- sleep 0.5
31
- forker.abort
32
- sleep 0.1
33
- (ended_at - started_at).should be_close(0.5, 0.1)
34
- forker.running?.should == false
35
43
  end
36
44
  end
@@ -96,12 +96,12 @@ describe Spork::Server do
96
96
  File.read(FakeServer.helper_file).should include(File.read(FakeServer::BOOTSTRAP_FILE))
97
97
  end
98
98
 
99
- it "prevents you from running specs twice in parallel" do
99
+ it "aborts the current running thread when another run is started" do
100
100
  create_helper_file
101
101
  @fake.wait_time = 0.25
102
- first_run = Thread.new { @fake.run("test", STDOUT, STDIN).should == true }
102
+ first_run = Thread.new { @fake.run("test", STDOUT, STDIN).should == nil }
103
103
  sleep(0.05)
104
- @fake.run("test", STDOUT, STDIN).should == false
104
+ @fake.run("test", STDOUT, STDIN).should == true
105
105
 
106
106
  # wait for the first to finish
107
107
  first_run.join
@@ -57,6 +57,87 @@ describe Spork do
57
57
  end
58
58
 
59
59
  it "expands a caller line, preserving the line number" do
60
- Spork.expanded_caller("/boo/../yah.rb:31").should == "/yah.rb:31"
60
+ Spork.send(:expanded_caller, "/boo/../yah.rb:31").should == "/yah.rb:31"
61
+ end
62
+
63
+ describe "#trap_method" do
64
+ before(:each) do
65
+ Spork.using_spork!
66
+
67
+ Object.class_eval do
68
+ class TrapTest
69
+ def self.output
70
+ @output ||= []
71
+ end
72
+
73
+ def hello
74
+ TrapTest.output << 'hello'
75
+ end
76
+
77
+ def goodbye
78
+ TrapTest.output << 'goodbye'
79
+ end
80
+
81
+ def say_something!
82
+ TrapTest.output << 'something'
83
+ end
84
+ end
85
+ end
86
+ @trap_test = TrapTest.new
87
+ end
88
+
89
+ after(:each) do
90
+ Object.send(:remove_const, :TrapTest)
91
+ end
92
+
93
+ it "delays execution of a method until after Spork.exec_each_run is called" do
94
+ Spork.using_spork!
95
+ Spork.trap_method(TrapTest, :hello)
96
+ @trap_test.hello
97
+ @trap_test.goodbye
98
+ Spork.exec_each_run
99
+ TrapTest.output.should == ['goodbye', 'hello']
100
+ end
101
+
102
+ it "works with methods that have punctuation" do
103
+ Spork.trap_method(TrapTest, :say_something!)
104
+ @trap_test.say_something!
105
+ TrapTest.output.should == []
106
+ Spork.exec_each_run
107
+ TrapTest.output.should == ['something']
108
+ end
109
+ end
110
+
111
+ describe "#trap_class_method" do
112
+ before(:each) do
113
+ Object.class_eval do
114
+ class TrapTest
115
+ def self.output
116
+ @output ||= []
117
+ end
118
+
119
+ def self.hello
120
+ output << 'hello'
121
+ end
122
+
123
+ def self.goodbye
124
+ output << 'goodbye'
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ after(:each) do
131
+ Object.send(:remove_const, :TrapTest)
132
+ end
133
+
134
+ it "delays execution of a method until after Spork.exec_each_run is called" do
135
+ Spork.using_spork!
136
+ Spork.trap_class_method(TrapTest, :hello)
137
+ TrapTest.hello
138
+ TrapTest.goodbye
139
+ Spork.exec_each_run
140
+ TrapTest.output.should == ['goodbye', 'hello']
141
+ end
61
142
  end
62
143
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.5.7
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-10 00:00:00 -06:00
12
+ date: 2009-06-17 00:00:00 -06:00
13
13
  default_executable: spork
14
14
  dependencies: []
15
15