Roman2K-rails-test-serving 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,19 +1,7 @@
1
- Copyright (c) 2008 Roman Le Négrate
1
+ Copyright (c) 2008-2009 Roman Le Négrate
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9
4
 
10
- The above copyright notice and this permission notice shall be included in
11
- all copies or substantial portions of the Software.
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
6
 
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest CHANGED
@@ -1,6 +1,18 @@
1
+ lib/rails_test_serving/bootstrap.rb
2
+ lib/rails_test_serving/cleaner.rb
3
+ lib/rails_test_serving/client.rb
4
+ lib/rails_test_serving/constant_management.rb
5
+ lib/rails_test_serving/server.rb
6
+ lib/rails_test_serving/utilities.rb
1
7
  lib/rails_test_serving.rb
2
8
  LICENSE
3
- Rakefile
4
- README.rdoc
5
- test/rails_test_serving_test.rb
6
9
  Manifest
10
+ Rakefile
11
+ README.mdown
12
+ test/rails_test_serving/bootstrap_test.rb
13
+ test/rails_test_serving/cleaner_test.rb
14
+ test/rails_test_serving/client_test.rb
15
+ test/rails_test_serving/constant_management_test.rb
16
+ test/rails_test_serving/server_test.rb
17
+ test/rails_test_serving/utilities_test.rb
18
+ test/test_helper.rb
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'echoe'
2
2
 
3
- Echoe.new('rails-test-serving', '0.1.3') do |p|
3
+ Echoe.new('rails-test-serving', '0.1.4') do |p|
4
4
  p.description = "Makes unit tests of a Rails application run instantly"
5
5
  p.url = "https://github.com/Roman2K/rails-test-serving"
6
6
  p.author = "Roman Le Négrate"
7
7
  p.email = "roman.lenegrate@gmail.com"
8
8
  p.ignore_pattern = "*.gemspec"
9
9
  p.development_dependencies = []
10
- p.rdoc_options = %w(--main README.rdoc --inline-source --line-numbers --charset UTF-8)
10
+ p.rdoc_options = %w(--main README.mdown --inline-source --line-numbers --charset UTF-8)
11
11
  end
@@ -10,404 +10,13 @@ module RailsTestServing
10
10
  end
11
11
  class ServerUnavailable < StandardError
12
12
  end
13
-
14
- SOCKET_PATH = ['tmp', 'sockets', 'test_server.sock']
15
-
16
- def self.service_uri
17
- @service_uri ||= begin
18
- # Determine RAILS_ROOT
19
- root, max_depth = Pathname('.'), Pathname.pwd.expand_path.to_s.split(File::SEPARATOR).size
20
- until root.join('config', 'boot.rb').file?
21
- root = root.parent
22
- if root.to_s.split(File::SEPARATOR).size >= max_depth
23
- raise "RAILS_ROOT could not be determined"
24
- end
25
- end
26
- root = root.cleanpath
27
-
28
- # Adjust load path
29
- $: << root.to_s << root.join('test').to_s
30
-
31
- # Ensure socket directory exists
32
- path = root.join(*SOCKET_PATH)
33
- path.dirname.mkpath
34
-
35
- # URI
36
- "drbunix:#{path}"
37
- end
38
- end
39
-
40
- def self.boot(argv=ARGV)
41
- if argv.delete('--serve')
42
- Server.start
43
- elsif !argv.delete('--local')
44
- Client.run_tests
45
- end
46
- end
47
-
48
- def self.options
49
- @options ||= begin
50
- options = $test_server_options || {}
51
- options[:reload] ||= []
52
- options
53
- end
54
- end
55
-
56
- module ConstantManagement
57
- extend self
58
-
59
- def legit?(const)
60
- !const.to_s.empty? && constantize(const) == const
61
- end
62
-
63
- def constantize(name)
64
- eval("#{name} if defined? #{name}", TOPLEVEL_BINDING)
65
- end
66
-
67
- def constantize!(name)
68
- name.to_s.split('::').inject(Object) { |namespace, short| namespace.const_get(short) }
69
- end
70
-
71
- # ActiveSupport's Module#remove_class doesn't behave quite the way I would expect it to.
72
- def remove_constants(*names)
73
- names.map do |name|
74
- namespace, short = name.to_s =~ /^(.+)::(.+?)$/ ? [$1, $2] : ['Object', name]
75
- constantize!(namespace).module_eval { remove_const(short) if const_defined?(short) }
76
- end
77
- end
78
-
79
- def subclasses_of(parent, options={})
80
- children = []
81
- ObjectSpace.each_object(Class) { |klass| children << klass if klass < parent && (!options[:legit] || legit?(klass)) }
82
- children
83
- end
84
- end
85
-
86
- module Client
87
- extend self
88
-
89
- # Setting this variable to true inhibits #run_tests.
90
- @@disabled = false
91
-
92
- def disable
93
- @@disabled = true
94
- yield
95
- ensure
96
- @@disabled = false
97
- end
98
-
99
- def tests_on_exit
100
- !Test::Unit.run?
101
- end
102
-
103
- def tests_on_exit=(yes)
104
- Test::Unit.run = !yes
105
- end
106
-
107
- def run_tests
108
- return if @@disabled
109
- run_tests!
110
- end
111
-
112
- private
113
-
114
- def run_tests!
115
- handle_process_lifecycle do
116
- server = DRbObject.new_with_uri(RailsTestServing.service_uri)
117
- begin
118
- puts(server.run($0, ARGV))
119
- rescue DRb::DRbConnError
120
- raise ServerUnavailable
121
- end
122
- end
123
- end
124
-
125
- def handle_process_lifecycle
126
- Client.tests_on_exit = false
127
- begin
128
- yield
129
- rescue ServerUnavailable, InvalidArgumentPattern
130
- Client.tests_on_exit = true
131
- else
132
- # TODO exit with a status code reflecting the result of the tests
133
- exit 0
134
- end
135
- end
136
- end
137
-
138
- class Server
139
- GUARD = Mutex.new
140
-
141
- def self.start
142
- DRb.start_service(RailsTestServing.service_uri, Server.new)
143
- DRb.thread.join
144
- end
145
-
146
- def initialize
147
- ENV['RAILS_ENV'] = 'test'
148
- enable_dependency_tracking
149
- start_cleaner
150
- load_framework
151
- log "** Test server started (##{$$})\n"
152
- end
153
-
154
- def run(file, argv)
155
- GUARD.synchronize { perform_run(file, argv) }
156
- end
157
-
158
- private
159
-
160
- def log(message)
161
- $stdout.print(message)
162
- $stdout.flush
163
- end
164
-
165
- # TODO clean this up, making 'path' a Pathname instead of a String
166
- def shorten_path(path)
167
- shortenable, base = File.expand_path(path), File.expand_path(Dir.pwd)
168
- attempt = shortenable.sub(/^#{Regexp.escape base + File::SEPARATOR}/, '')
169
- attempt.length < path.length ? attempt : path
170
- end
171
-
172
- def enable_dependency_tracking
173
- require 'config/boot'
174
-
175
- Rails::Configuration.class_eval do
176
- unless method_defined? :cache_classes
177
- raise "#{self.class} out of sync with current Rails version"
178
- end
179
-
180
- def cache_classes
181
- false
182
- end
183
- end
184
- end
185
-
186
- def start_cleaner
187
- @cleaner = Cleaner.new
188
- end
189
-
190
- def load_framework
191
- Client.disable do
192
- $: << 'test'
193
- require 'test_helper'
194
- end
195
- end
196
-
197
- def perform_run(file, argv)
198
- sanitize_arguments! file, argv
199
-
200
- log ">> " + [shorten_path(file), *argv].join(' ')
201
-
202
- result = nil
203
- elapsed = Benchmark.realtime do
204
- result = capture_test_result(file, argv)
205
- end
206
- log " (%d ms)\n" % (elapsed * 1000)
207
- result
208
- end
209
-
210
- def sanitize_arguments!(file, argv)
211
- if file =~ /^-/
212
- # No file was specified for loading, only options. It's the case with
213
- # Autotest.
214
- raise InvalidArgumentPattern
215
- end
216
-
217
- # Filter out the junk that TextMate seems to inject into ARGV when running
218
- # focused tests.
219
- while a = find_index_by_pattern(argv, /^\[/) and z = find_index_by_pattern(argv[a..-1], /\]$/)
220
- argv[a..a+z] = []
221
- end
222
- end
223
-
224
- def capture_test_result(file, argv)
225
- result = []
226
- @cleaner.clean_up_around do
227
- result << capture_standard_stream('err') do
228
- result << capture_standard_stream('out') do
229
- result << capture_testrunner_result do
230
- fix_objectspace_collector do
231
- Client.disable { load(file) }
232
- Test::Unit::AutoRunner.run(false, nil, argv)
233
- end
234
- end
235
- end
236
- end
237
- end
238
- result.reverse.join
239
- end
240
-
241
- def capture_standard_stream(name)
242
- eval("old, $std#{name} = $std#{name}, StringIO.new")
243
- begin
244
- yield
245
- return eval("$std#{name}").string
246
- ensure
247
- eval("$std#{name} = old")
248
- end
249
- end
250
-
251
- def capture_testrunner_result
252
- set_default_testrunner_stream(io = StringIO.new) { yield }
253
- io.string
254
- end
255
-
256
- # The default output stream of TestRunner is STDOUT which cannot be captured
257
- # and, as a consequence, neither can TestRunner output when not instantiated
258
- # explicitely. The following method can change the default output stream
259
- # argument so that it can be set to a stream that can be captured instead.
260
- def set_default_testrunner_stream(io)
261
- require 'test/unit/ui/console/testrunner'
262
-
263
- Test::Unit::UI::Console::TestRunner.class_eval do
264
- alias_method :old_initialize, :initialize
265
- def initialize(suite, output_level, io=Thread.current["test_runner_io"])
266
- old_initialize(suite, output_level, io)
267
- end
268
- end
269
- Thread.current["test_runner_io"] = io
270
-
271
- begin
272
- return yield
273
- ensure
274
- Thread.current["test_runner_io"] = nil
275
- Test::Unit::UI::Console::TestRunner.class_eval do
276
- alias_method :initialize, :old_initialize
277
- remove_method :old_initialize
278
- end
279
- end
280
- end
281
-
282
- # The stock ObjectSpace collector collects every single class that inherits
283
- # from Test::Unit, including those which have just been unassigned from
284
- # their constant and not yet garbage collected. This method fixes that
285
- # behaviour by filtering out these soon-to-be-garbage-collected classes.
286
- def fix_objectspace_collector
287
- require 'test/unit/collector/objectspace'
288
-
289
- Test::Unit::Collector::ObjectSpace.class_eval do
290
- alias_method :old_collect, :collect
291
- def collect(name)
292
- tests = []
293
- ConstantManagement.subclasses_of(Test::Unit::TestCase, :legit => true).each { |klass| add_suite(tests, klass.suite) }
294
- suite = Test::Unit::TestSuite.new(name)
295
- sort(tests).each { |t| suite << t }
296
- suite
297
- end
298
- end
299
-
300
- begin
301
- return yield
302
- ensure
303
- Test::Unit::Collector::ObjectSpace.class_eval do
304
- alias_method :collect, :old_collect
305
- remove_method :old_collect
306
- end
307
- end
308
- end
309
-
310
- private
311
-
312
- def find_index_by_pattern(enumerable, pattern)
313
- enumerable.each_with_index do |element, index|
314
- return index if pattern === element
315
- end
316
- nil
317
- end
318
- end
319
-
320
- class Cleaner
321
- include ConstantManagement
322
-
323
- BREATH = 0.01
324
- TESTCASE_CLASS_NAMES = %w( Test::Unit::TestCase
325
- ActiveSupport::TestCase
326
- ActionView::TestCase
327
- ActionController::TestCase
328
- ActionController::IntegrationTest
329
- ActionMailer::TestCase )
330
-
331
- def initialize
332
- start_worker
333
- end
334
-
335
- def clean_up_around
336
- check_worker_health
337
- sleep BREATH while @working
338
- begin
339
- reload_app
340
- yield
341
- ensure
342
- @working = true
343
- sleep BREATH until @worker.stop?
344
- @worker.wakeup
345
- end
346
- end
347
-
348
- private
349
-
350
- def start_worker
351
- @worker = Thread.new do
352
- Thread.abort_on_exception = true
353
- loop do
354
- Thread.stop
355
- begin
356
- clean_up_app
357
- remove_tests
358
- ensure
359
- @working = false
360
- end
361
- end
362
- end
363
- @working = false
364
- end
365
-
366
- def check_worker_health
367
- unless @worker.alive?
368
- $stderr.puts "cleaning thread died, restarting"
369
- start_worker
370
- end
371
- end
372
-
373
- def clean_up_app
374
- ActionController::Dispatcher.new(StringIO.new).cleanup_application
375
- if defined?(Fixtures) && Fixtures.respond_to?(:reset_cache)
376
- Fixtures.reset_cache
377
- end
378
-
379
- # Reload files that match :reload here instead of in reload_app since the
380
- # :reload option is intended to target files that don't change between two
381
- # consecutive runs (an external library for example). That way, they are
382
- # reloaded in the background instead of slowing down the next run.
383
- reload_specified_source_files
384
- end
385
-
386
- def remove_tests
387
- TESTCASE_CLASS_NAMES.each do |name|
388
- next unless klass = constantize(name)
389
- remove_constants(*subclasses_of(klass).map { |c| c.to_s }.grep(/Test$/) - TESTCASE_CLASS_NAMES)
390
- end
391
- end
392
-
393
- def reload_app
394
- ActionController::Dispatcher.new(StringIO.new).reload_application
395
- end
396
-
397
- def reload_specified_source_files
398
- to_reload =
399
- $".select do |path|
400
- RailsTestServing.options[:reload].any? do |matcher|
401
- matcher === path
402
- end
403
- end
404
-
405
- # Force a reload by removing matched files from $"
406
- $".replace($" - to_reload)
407
-
408
- to_reload.each do |file|
409
- require file
410
- end
411
- end
412
- end
413
- end unless defined? RailsTestServing
13
+
14
+ autoload :Bootstrap, 'rails_test_serving/bootstrap'
15
+ autoload :Server, 'rails_test_serving/server'
16
+ autoload :Client, 'rails_test_serving/client'
17
+ autoload :Cleaner, 'rails_test_serving/cleaner'
18
+ autoload :ConstantManagement, 'rails_test_serving/constant_management'
19
+ autoload :Utilities, 'rails_test_serving/utilities'
20
+
21
+ extend Bootstrap
22
+ end
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rails-test-serving}
5
- s.version = "0.1.3"
5
+ s.version = "0.1.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Roman Le N\303\251grate"]
9
- s.date = %q{2008-11-21}
9
+ s.date = %q{2009-02-08}
10
10
  s.description = %q{Makes unit tests of a Rails application run instantly}
11
11
  s.email = %q{roman.lenegrate@gmail.com}
12
12
  s.extra_rdoc_files = ["lib/rails_test_serving.rb", "LICENSE", "README.rdoc"]
13
- s.files = ["lib/rails_test_serving.rb", "LICENSE", "Rakefile", "README.rdoc", "test/rails_test_serving_test.rb", "Manifest", "rails-test-serving.gemspec"]
13
+ s.files = ["lib/rails_test_serving.rb", "LICENSE", "Rakefile", "README.rdoc", "test/rails_test_serving_test.rb", "Manifest", "rails-test-serving.gemspec", "test/rails_test_serving/bootstrap_test.rb", "test/rails_test_serving/cleaner_test.rb", "test/rails_test_serving/client_test.rb", "test/rails_test_serving/constant_management_test.rb", "test/rails_test_serving/server_test.rb", "test/rails_test_serving/utilities_test.rb", "test/test_helper.rb"]
14
14
  s.has_rdoc = true
15
15
  s.homepage = %q{https://github.com/Roman2K/rails-test-serving}
16
- s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers", "--charset", "UTF-8"]
16
+ s.rdoc_options = ["--main", "README.mdown", "--inline-source", "--line-numbers", "--charset", "UTF-8"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = %q{rails-test-serving}
19
19
  s.rubygems_version = %q{1.3.1}
20
20
  s.summary = %q{Makes unit tests of a Rails application run instantly}
21
- s.test_files = ["test/rails_test_serving_test.rb"]
21
+ s.test_files = ["test/rails_test_serving/bootstrap_test.rb", "test/rails_test_serving/cleaner_test.rb", "test/rails_test_serving/client_test.rb", "test/rails_test_serving/constant_management_test.rb", "test/rails_test_serving/server_test.rb", "test/rails_test_serving/utilities_test.rb", "test/test_helper.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::BootstrapTest < Test::Unit::TestCase
4
+ def setup
5
+ @boot = Object.new.extend RailsTestServing::Bootstrap
6
+ end
7
+
8
+ def test_service_uri
9
+ Pathname.stubs(:pwd).returns(Pathname("/foo/bar"))
10
+
11
+ # RAILS_ROOT is the current directory
12
+ setup_service_uri_test do
13
+ FileTest.expects(:file?).with("config/boot.rb").returns true
14
+ FileUtils.expects(:mkpath).with("tmp/sockets")
15
+ assert_equal "drbunix:tmp/sockets/test_server.sock", @boot.service_uri
16
+ end
17
+
18
+ # RAILS_ROOT is the parent directory
19
+ setup_service_uri_test do
20
+ FileTest.stubs(:file?).with("config/boot.rb").returns false
21
+ FileTest.stubs(:file?).with("../config/boot.rb").returns true
22
+ FileUtils.expects(:mkpath).with("../tmp/sockets")
23
+ assert_equal "drbunix:../tmp/sockets/test_server.sock", @boot.service_uri
24
+ end
25
+
26
+ # RAILS_ROOT cannot be determined
27
+ setup_service_uri_test do
28
+ FileTest.expects(:file?).with("config/boot.rb").returns false
29
+ FileTest.expects(:file?).with("../config/boot.rb").returns false
30
+ FileTest.expects(:file?).with("../../config/boot.rb").returns false
31
+ FileTest.expects(:file?).with("../../../config/boot.rb").never
32
+ FileUtils.expects(:mkpath).never
33
+ assert_raise(RuntimeError) { @boot.service_uri }
34
+ end
35
+ end
36
+
37
+ def test_boot
38
+ argv = []
39
+ RailsTestServing::Client.expects(:run_tests)
40
+ @boot.boot(argv)
41
+
42
+ argv = ['--local']
43
+ RailsTestServing::Client.expects(:run_tests).never
44
+ @boot.boot(argv)
45
+ assert_equal [], argv
46
+
47
+ argv = ["--serve"]
48
+ @boot.expects(:start_server)
49
+ @boot.boot(argv)
50
+ assert_equal [], argv
51
+ end
52
+
53
+ def test_options
54
+ @boot.instance_variable_set("@options", nil)
55
+ $test_server_options = nil
56
+ assert_equal({:reload => []}, @boot.options)
57
+
58
+ @boot.instance_variable_set("@options", nil)
59
+ $test_server_options = {:foo => :bar}
60
+ assert_equal({:foo => :bar, :reload => []}, @boot.options)
61
+
62
+ @boot.instance_variable_set("@options", nil)
63
+ $test_server_options = {:foo => :bar, :reload => [//]}
64
+ assert_equal({:foo => :bar, :reload => [//]}, @boot.options)
65
+ end
66
+
67
+ private
68
+
69
+ def setup_service_uri_test
70
+ old_load_path = $:.dup
71
+ begin
72
+ return yield
73
+ ensure
74
+ @boot.instance_variable_set("@service_uri", nil)
75
+ $:.replace(old_load_path)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::CleanerTest < Test::Unit::TestCase
4
+ include RailsTestServing
5
+
6
+ # private
7
+
8
+ def test_reload_specified_source_files
9
+ Cleaner.any_instance.stubs(:start_worker)
10
+
11
+ # Empty :reload option
12
+ preserve_features do
13
+ $".replace ["foo.rb"]
14
+ RailsTestServing.stubs(:options).returns({:reload => []})
15
+
16
+ Cleaner.any_instance.expects(:require).never
17
+ Cleaner.new.instance_eval { reload_specified_source_files }
18
+ assert_equal ["foo.rb"], $"
19
+ end
20
+
21
+ # :reload option contains regular expressions
22
+ preserve_features do
23
+ $".replace ["foo.rb", "bar.rb"]
24
+ RailsTestServing.stubs(:options).returns({:reload => [/foo/]})
25
+
26
+ Cleaner.any_instance.expects(:require).with("foo.rb").once
27
+ Cleaner.new.instance_eval { reload_specified_source_files }
28
+ assert_equal ["bar.rb"], $"
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def preserve_features
35
+ old = $".dup
36
+ begin
37
+ return yield
38
+ ensure
39
+ $".replace(old)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::ClientTest < Test::Unit::TestCase
4
+ def setup
5
+ @client = Object.new.extend RailsTestServing::Client
6
+ end
7
+
8
+ def test_run_tests
9
+ @client.expects(:run_tests!)
10
+ @client.run_tests
11
+
12
+ @client.disable do
13
+ @client.expects(:run_tests!).never
14
+ @client.run_tests
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::ConstantManagementTest < Test::Unit::TestCase
4
+ include RailsTestServing::ConstantManagement
5
+ NS = self
6
+
7
+ Foo = :foo
8
+ NamedFoo = Module.new
9
+ Namespace = Module.new
10
+
11
+ class A; end
12
+ class B < A; end
13
+ class C < B; end
14
+
15
+ def test_legit
16
+ assert legit?(NamedFoo)
17
+
18
+ assert !legit?("Inexistent")
19
+
20
+ fake = stub(:to_s => NamedFoo.to_s)
21
+ assert_equal NamedFoo.to_s, "#{fake}" # sanity check
22
+ assert !legit?(fake)
23
+ end
24
+
25
+ def test_constantize
26
+ assert_equal :foo, constantize("#{NS}::Foo")
27
+ assert_equal nil, constantize("#{NS}::Bar")
28
+ end
29
+
30
+ def test_constantize!
31
+ assert_equal :foo, constantize!("#{NS}::Foo")
32
+ assert_raise(NameError) { constantize!("#{NS}::Bar") }
33
+ end
34
+
35
+ def test_remove_constants
36
+ mod_A = Module.new
37
+ Namespace.const_set(:A, mod_A)
38
+ assert eval("defined? #{NS}::Namespace::A") # sanity check
39
+
40
+ removed = remove_constants("#{NS}::Namespace::A")
41
+ assert_equal [mod_A], removed
42
+ assert !eval("defined? #{NS}::Namespace::A")
43
+
44
+ removed = remove_constants("#{NS}::Namespace::A")
45
+ assert_equal [nil], removed
46
+ end
47
+
48
+ def test_subclasses_of
49
+ assert_equal [B, C], subclasses_of(A).sort_by { |c| c.name }
50
+ assert_equal [C], subclasses_of(B)
51
+ assert_equal [], subclasses_of(C)
52
+
53
+ self.stubs(:legit?).with(B).returns true
54
+ self.stubs(:legit?).with(C).returns false
55
+ assert_equal [B], subclasses_of(A, :legit => true)
56
+ end
57
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::ServerTest < Test::Unit::TestCase
4
+
5
+ # private
6
+
7
+ def test_perform_run
8
+ server = stub_server
9
+ file, argv = "test.rb", ["-n", "/pat/"]
10
+
11
+ server.stubs(:sanitize_arguments!)
12
+ server.stubs(:log).with(">> test.rb -n /pat/").yields.returns("result").once
13
+ server.stubs(:capture_test_result).with(file, argv)
14
+
15
+ result = server.instance_eval { perform_run(file, argv) }
16
+ assert_equal "result", result
17
+ end
18
+
19
+ def test_sanitize_arguments
20
+ server = stub_server
21
+ sanitize = lambda { |*args| server.instance_eval { sanitize_arguments! *args } }
22
+
23
+ # valid
24
+ file, argv = "test.rb", ["--name=test_create"]
25
+ sanitize.call file, argv
26
+
27
+ assert_equal "test.rb", file
28
+ assert_equal ["--name=test_create"], argv
29
+
30
+ # TextMate junk
31
+ junk = ["[test_create,", "nil,", "nil]"]
32
+
33
+ # a) at the beginning
34
+ file, argv = "test.rb", junk + ["foo"]
35
+ sanitize.call file, argv
36
+
37
+ assert_equal "test.rb", file
38
+ assert_equal ["foo"], argv
39
+
40
+ # b) in between normal arguments
41
+ file, argv = "test.rb", ["foo"] + junk + ["bar"]
42
+ sanitize.call file, argv
43
+
44
+ assert_equal "test.rb", file
45
+ assert_equal ["foo", "bar"], argv
46
+
47
+ # invalid arguments
48
+ assert_raise RailsTestServing::InvalidArgumentPattern do
49
+ sanitize.call "-e", ["code"]
50
+ end
51
+ end
52
+
53
+ def test_capture_test_result
54
+ server = stub_server
55
+ cleaner = server.instance_variable_set("@cleaner", stub)
56
+
57
+ cleaner.stubs(:clean_up_around).yields
58
+ server.stubs(:capture_standard_stream).with('err').yields.returns "stderr"
59
+ server.stubs(:capture_standard_stream).with('out').yields.returns "stdout"
60
+ server.stubs(:capture_testrunner_result).yields.returns "result"
61
+ server.stubs(:fix_objectspace_collector).yields
62
+
63
+ server.stubs(:load).with("file")
64
+ Test::Unit::AutoRunner.expects(:run).with(false, nil, "argv")
65
+
66
+ result = server.instance_eval { capture_test_result("file", "argv") }
67
+ assert_equal "stderrstdoutresult", result
68
+ end
69
+
70
+ private
71
+
72
+ def stub_server
73
+ RailsTestServing::Server.new
74
+ end
75
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ class RailsTestServing::UtilitiesTest < Test::Unit::TestCase
4
+ def setup
5
+ @utils = Object.new.extend RailsTestServing::Utilities
6
+ end
7
+
8
+ def test_log
9
+ # Blockless form
10
+ stream = StringIO.new
11
+ result = @utils.instance_eval { log("message", stream) }
12
+ assert_equal "message", stream.string
13
+ assert_equal nil, result
14
+
15
+ # Block form
16
+ stream = StringIO.new
17
+ Benchmark.stubs(:realtime).yields.returns 1
18
+ yielded = []
19
+ result = @utils.instance_eval { log("message", stream) { yielded << true; "result" } }
20
+ assert_equal "message (1000 ms)\n", stream.string
21
+ assert_equal [true], yielded
22
+ assert_equal "result", result
23
+ end
24
+
25
+ def test_capture_standard_stream
26
+ assert_equal STDOUT, $stdout # sanity check
27
+
28
+ captured = @utils.instance_eval { capture_standard_stream('out') { print "test" } }
29
+
30
+ assert_equal "test", captured
31
+ assert_equal STDOUT, $stdout
32
+ end
33
+
34
+ def test_capture_testrunner_result
35
+ captured = @utils.instance_eval do
36
+ capture_testrunner_result { Thread.current["test_runner_io"].print "test" }
37
+ end
38
+ assert_equal "test", captured
39
+ end
40
+
41
+ def test_shorten_path
42
+ Dir.stubs(:pwd).returns '/base'
43
+
44
+ assert_equal 'test.rb', @utils.shorten_path('test.rb')
45
+ assert_equal 'test.rb', @utils.shorten_path('/base/test.rb')
46
+ assert_equal 'test.rb', @utils.shorten_path('/base/./test.rb')
47
+ assert_equal '/other-base/test.rb', @utils.shorten_path('/other-base/test.rb')
48
+ assert_equal '/other-base/test.rb', @utils.shorten_path('/other-base/././test.rb')
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+
3
+ require 'test/unit'
4
+ require 'mocha'
5
+ Mocha::Configuration.prevent :stubbing_non_existent_method
6
+ Mocha::Configuration.warn_when :stubbing_method_unnecessarily
7
+
8
+ require 'rails_test_serving'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Roman2K-rails-test-serving
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Roman Le N\xC3\xA9grate"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-21 00:00:00 -08:00
12
+ date: 2009-02-08 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -31,12 +31,19 @@ files:
31
31
  - test/rails_test_serving_test.rb
32
32
  - Manifest
33
33
  - rails-test-serving.gemspec
34
+ - test/rails_test_serving/bootstrap_test.rb
35
+ - test/rails_test_serving/cleaner_test.rb
36
+ - test/rails_test_serving/client_test.rb
37
+ - test/rails_test_serving/constant_management_test.rb
38
+ - test/rails_test_serving/server_test.rb
39
+ - test/rails_test_serving/utilities_test.rb
40
+ - test/test_helper.rb
34
41
  has_rdoc: true
35
42
  homepage: https://github.com/Roman2K/rails-test-serving
36
43
  post_install_message:
37
44
  rdoc_options:
38
45
  - --main
39
- - README.rdoc
46
+ - README.mdown
40
47
  - --inline-source
41
48
  - --line-numbers
42
49
  - --charset
@@ -63,4 +70,10 @@ signing_key:
63
70
  specification_version: 2
64
71
  summary: Makes unit tests of a Rails application run instantly
65
72
  test_files:
66
- - test/rails_test_serving_test.rb
73
+ - test/rails_test_serving/bootstrap_test.rb
74
+ - test/rails_test_serving/cleaner_test.rb
75
+ - test/rails_test_serving/client_test.rb
76
+ - test/rails_test_serving/constant_management_test.rb
77
+ - test/rails_test_serving/server_test.rb
78
+ - test/rails_test_serving/utilities_test.rb
79
+ - test/test_helper.rb
data/README.rdoc DELETED
@@ -1,63 +0,0 @@
1
- Tired of waiting 10 seconds before your tests run? RailsTestServing can make them run almost instantly.
2
-
3
- == Usage
4
-
5
- 1. Install the gem:
6
- gem install Roman2K-rails-test-serving -v '>= 0.1.3' -s http://gems.github.com
7
-
8
- 2. Insert the following lines at the very top of <tt>test/test_helper.rb</tt>:
9
- require 'rubygems'
10
- require 'rails_test_serving'
11
- RailsTestServing.boot
12
-
13
- 3. Append the following line to <tt>~/.bash_profile</tt>:
14
- export RUBYLIB=".:test:$RUBYLIB"
15
-
16
- If you get loading errors during the next steps:
17
- * Move the +RUBYLIB+ line from <tt>~/.bash_profile</tt> to <tt>~/.bash_login</tt> instead.
18
- * If you are using TextMate, you may try to apply {this (hopefully temporary) fix}[http://roman.flucti.com/textmate-fix-for-relative-require-test_helper].
19
-
20
- 4. Start the server:
21
- cd <project-dir>
22
- ruby test/test_helper.rb --serve
23
-
24
- 5. Run tests as you usually do:
25
- ruby test/unit/account_test.rb
26
- ruby test/unit/account_test.rb -n /balance/
27
- As a consequence, they work in RubyMate too (⌘R in TextMate).
28
-
29
- 6. Details in the {introduction article}[http://roman.flucti.com/a-test-server-for-rails-applications].
30
-
31
- <b>Note:</b> if the server is not started, tests fall back to running the usual way.
32
-
33
- == Options
34
-
35
- An option hash can be specified for RailsTestServing to use, by defining <tt>$test_server_options</tt> right before <tt>require 'rails_test_serving'</tt>. It must be a hash with symbol keys. Currently available options are:
36
- +reload+:: An array of regular expressions (or any object responding to <tt>#===</tt>) matching the name of the files that should be forced to reload right after the regular constant cleanup. Note that the constants these files have defined are not removed before the new +require+.
37
-
38
- Example <tt>test_helper.rb</tt> head:
39
- require 'rubygems'
40
-
41
- $test_server_options = { :reload => [/blueprint/] }
42
- require 'rails_test_serving'
43
- RailsTestServing.boot
44
-
45
- # ...remainder here...
46
-
47
- == Caveats
48
-
49
- * Tested working with Rails 2.1.2 up to 2.2.0 RC2. Compatibility with versions of Rails out of that range is guaranteed.
50
- * There might exist some quirks: search for "TODO" in the source. I can bear them but contributions are welcome.
51
- * Some unit tests are left to be written.
52
-
53
- == Credits
54
-
55
- Code:
56
- * {Roman Le Négrate}[http://roman.flucti.com], a.k.a. Roman2K ({contact}[mailto:roman.lenegrate@gmail.com])
57
- * {Jack Chen}[http://github.com/chendo], a.k.a. chendo
58
-
59
- Feedback:
60
- * Justin Ko
61
- * {Dr Nic Williams}[http://drnicwilliams.com]
62
-
63
- Released under the MIT license: see the +LICENSE+ file.
@@ -1,294 +0,0 @@
1
- require 'rubygems'
2
-
3
- require 'test/unit'
4
- require 'mocha'
5
- Mocha::Configuration.prevent :stubbing_non_existent_method
6
- Mocha::Configuration.warn_when :stubbing_method_unnecessarily
7
-
8
- require 'rails_test_serving'
9
-
10
- class RailsTestServingTest < Test::Unit::TestCase
11
- include RailsTestServing
12
-
13
- # class
14
-
15
- def test_service_uri
16
- # RAILS_ROOT is the current directory
17
- setup_service_uri_test do
18
- FileTest.expects(:file?).with("config/boot.rb").returns true
19
- FileUtils.expects(:mkpath).with("tmp/sockets")
20
- assert_equal "drbunix:tmp/sockets/test_server.sock", RailsTestServing.service_uri
21
- end
22
-
23
- # RAILS_ROOT is in the parent directory
24
- setup_service_uri_test do
25
- FileTest.stubs(:file?).with("config/boot.rb").returns false
26
- FileTest.stubs(:file?).with("../config/boot.rb").returns true
27
- FileUtils.expects(:mkpath).with("../tmp/sockets")
28
- assert_equal "drbunix:../tmp/sockets/test_server.sock", RailsTestServing.service_uri
29
- end
30
-
31
- # RAILS_ROOT cannot be determined
32
- setup_service_uri_test do
33
- Pathname.stubs(:pwd).returns(Pathname("/foo/bar"))
34
- FileTest.expects(:file?).with("config/boot.rb").returns false
35
- FileTest.expects(:file?).with("../config/boot.rb").returns false
36
- FileTest.expects(:file?).with("../../config/boot.rb").returns false
37
- FileTest.expects(:file?).with("../../../config/boot.rb").never
38
- FileUtils.expects(:mkpath).never
39
- assert_raise(RuntimeError) { RailsTestServing.service_uri }
40
- end
41
- end
42
-
43
- def test_boot
44
- argv = []
45
- Client.expects(:run_tests)
46
- RailsTestServing.boot(argv)
47
-
48
- argv = ['--local']
49
- Client.expects(:run_tests).never
50
- RailsTestServing.boot(argv)
51
- assert_equal [], argv
52
-
53
- argv = ["--serve"]
54
- Server.expects(:start)
55
- RailsTestServing.boot(argv)
56
- assert_equal [], argv
57
- end
58
-
59
- private
60
-
61
- def setup_service_uri_test(wont_mkpath=false)
62
- old_load_path = $:.dup
63
- begin
64
- return yield
65
- ensure
66
- RailsTestServing.instance_variable_set(:@service_uri, nil)
67
- $:.replace(old_load_path)
68
- end
69
- end
70
- end
71
-
72
- class RailsTestServing::ConstantManagementTest < Test::Unit::TestCase
73
- include RailsTestServing::ConstantManagement
74
- NS = self
75
-
76
- Foo = :foo
77
- NamedFoo = Module.new
78
- Namespace = Module.new
79
-
80
- class A; end
81
- class B < A; end
82
- class C < B; end
83
-
84
- def test_legit
85
- assert legit?(NamedFoo)
86
-
87
- assert !legit?("Inexistent")
88
-
89
- fake = stub(:to_s => NamedFoo.to_s)
90
- assert_equal NamedFoo.to_s, "#{fake}" # sanity check
91
- assert !legit?(fake)
92
- end
93
-
94
- def test_constantize
95
- assert_equal :foo, constantize("#{NS}::Foo")
96
- assert_equal nil, constantize("#{NS}::Bar")
97
- end
98
-
99
- def test_constantize!
100
- assert_equal :foo, constantize!("#{NS}::Foo")
101
- assert_raise(NameError) { constantize!("#{NS}::Bar") }
102
- end
103
-
104
- def test_remove_constants
105
- mod_A = Module.new
106
- Namespace.const_set(:A, mod_A)
107
- assert eval("defined? #{NS}::Namespace::A") # sanity check
108
-
109
- removed = remove_constants("#{NS}::Namespace::A")
110
- assert_equal [mod_A], removed
111
- assert !eval("defined? #{NS}::Namespace::A")
112
-
113
- removed = remove_constants("#{NS}::Namespace::A")
114
- assert_equal [nil], removed
115
- end
116
-
117
- def test_subclasses_of
118
- assert_equal [C, B], subclasses_of(A)
119
- assert_equal [C], subclasses_of(B)
120
- assert_equal [], subclasses_of(C)
121
-
122
- self.stubs(:legit?).with(B).returns true
123
- self.stubs(:legit?).with(C).returns false
124
- assert_equal [B], subclasses_of(A, :legit => true)
125
- end
126
- end
127
-
128
- class RailsTestServing::ClientTest < Test::Unit::TestCase
129
- C = RailsTestServing::Client
130
-
131
- def test_run_tests
132
- C.expects(:run_tests!)
133
- C.run_tests
134
-
135
- C.disable do
136
- C.expects(:run_tests!).never
137
- C.run_tests
138
- end
139
- end
140
- end
141
-
142
- class RailsTestServing::ServerTest < Test::Unit::TestCase
143
-
144
- # private
145
-
146
- def test_perform_run
147
- server = stub_server
148
- file, argv = "test.rb", ["-n", "/pat/"]
149
-
150
- server.stubs(:sanitize_arguments!)
151
- Benchmark.stubs(:realtime).yields.returns 1
152
-
153
- server.expects(:log).with(">> test.rb -n /pat/").once
154
- server.stubs(:capture_test_result).with(file, argv).returns "result"
155
- server.expects(:log).with(" (1000 ms)\n").once
156
-
157
- result = server.instance_eval { perform_run(file, argv) }
158
- assert_equal "result", result
159
- end
160
-
161
- def test_sanitize_arguments
162
- server = stub_server
163
- sanitize = lambda { |*args| server.instance_eval { sanitize_arguments! *args } }
164
-
165
- # valid
166
- file, argv = "test.rb", ["--name=test_create"]
167
- sanitize.call file, argv
168
-
169
- assert_equal "test.rb", file
170
- assert_equal ["--name=test_create"], argv
171
-
172
- # TextMate junk
173
- junk = ["[test_create,", "nil,", "nil]"]
174
-
175
- # a) at the beginning
176
- file, argv = "test.rb", junk + ["foo"]
177
- sanitize.call file, argv
178
-
179
- assert_equal "test.rb", file
180
- assert_equal ["foo"], argv
181
-
182
- # b) in between normal arguments
183
- file, argv = "test.rb", ["foo"] + junk + ["bar"]
184
- sanitize.call file, argv
185
-
186
- assert_equal "test.rb", file
187
- assert_equal ["foo", "bar"], argv
188
-
189
- # invalid arguments
190
- assert_raise RailsTestServing::InvalidArgumentPattern do
191
- sanitize.call "-e", ["code"]
192
- end
193
- end
194
-
195
- def test_shorten_path
196
- server = stub_server
197
- Dir.stubs(:pwd).returns '/base'
198
-
199
- assert_equal 'test.rb', server.instance_eval { shorten_path 'test.rb' }
200
- assert_equal 'test.rb', server.instance_eval { shorten_path '/base/test.rb' }
201
- assert_equal '/other-base/test.rb', server.instance_eval { shorten_path '/other-base/test.rb' }
202
- assert_equal '/other-base/test.rb', server.instance_eval { shorten_path '/other-base/././test.rb' }
203
- end
204
-
205
- def test_capture_test_result
206
- server = stub_server
207
- cleaner = server.instance_variable_set(:@cleaner, stub)
208
-
209
- cleaner.stubs(:clean_up_around).yields
210
- server.stubs(:capture_standard_stream).with('err').yields.returns "stderr"
211
- server.stubs(:capture_standard_stream).with('out').yields.returns "stdout"
212
- server.stubs(:capture_testrunner_result).yields.returns "result"
213
- server.stubs(:fix_objectspace_collector).yields
214
-
215
- server.stubs(:load).with("file")
216
- Test::Unit::AutoRunner.expects(:run).with(false, nil, "argv")
217
-
218
- result = server.instance_eval { capture_test_result("file", "argv") }
219
- assert_equal "stderrstdoutresult", result
220
- end
221
-
222
- def test_capture_standard_stream
223
- server = stub_server
224
- assert_equal STDOUT, $stdout # sanity check
225
-
226
- captured = server.instance_eval { capture_standard_stream('out') { print "test" } }
227
-
228
- assert_equal "test", captured
229
- assert_equal STDOUT, $stdout
230
- end
231
-
232
- def test_capture_testrunner_result
233
- server = stub_server
234
-
235
- captured = server.instance_eval do
236
- capture_testrunner_result { Thread.current["test_runner_io"].print "test" }
237
- end
238
-
239
- assert_equal "test", captured
240
- end
241
-
242
- private
243
-
244
- S = RailsTestServing::Server
245
-
246
- def stub_server
247
- S.any_instance.stubs(:enable_dependency_tracking)
248
- S.any_instance.stubs(:start_cleaner)
249
- S.any_instance.stubs(:load_framework)
250
- S.any_instance.stubs(:log)
251
- S.new
252
- end
253
- end
254
-
255
- class RailsTestServing::CleanerTest < Test::Unit::TestCase
256
- include RailsTestServing
257
-
258
- # private
259
-
260
- def test_reload_specified_source_files
261
- Cleaner.any_instance.stubs(:start_worker)
262
-
263
- # Empty :reload option
264
- preserve_features do
265
- $".replace ["foo.rb"]
266
- RailsTestServing.stubs(:options).returns({:reload => []})
267
-
268
- Cleaner.any_instance.expects(:require).never
269
- Cleaner.new.instance_eval { reload_specified_source_files }
270
- assert_equal ["foo.rb"], $"
271
- end
272
-
273
- # :reload option contains regular expressions
274
- preserve_features do
275
- $".replace ["foo.rb", "bar.rb"]
276
- RailsTestServing.stubs(:options).returns({:reload => [/foo/]})
277
-
278
- Cleaner.any_instance.expects(:require).with("foo.rb").once
279
- Cleaner.new.instance_eval { reload_specified_source_files }
280
- assert_equal ["bar.rb"], $"
281
- end
282
- end
283
-
284
- private
285
-
286
- def preserve_features
287
- old = $".dup
288
- begin
289
- return yield
290
- ensure
291
- $".replace(old)
292
- end
293
- end
294
- end