Roman2K-rails-test-serving 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README.rdoc +28 -0
- data/Rakefile +11 -0
- data/lib/rails_test_serving.rb +352 -0
- data/rails-test-serving.gemspec +68 -0
- data/test/rails_test_serving_test.rb +211 -0
- metadata +65 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Roman Le Négrate
|
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:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Tired of waiting 10 seconds before your tests run? RailsTestServing can make them run almost instantly. Details in the {introduction article}[http://roman.flucti.com/a-test-server-for-rails-applications].
|
2
|
+
|
3
|
+
== Quick usage instructions
|
4
|
+
|
5
|
+
1. Insert the following lines at the very top of <tt>test/test_helper.rb</tt>:
|
6
|
+
require 'rails_test_serving'
|
7
|
+
RailsTestServing.boot
|
8
|
+
|
9
|
+
2. Start the server:
|
10
|
+
cd <project-dir>
|
11
|
+
ruby test/test_helper.rb --serve
|
12
|
+
|
13
|
+
3. Run tests as you usually do:
|
14
|
+
ruby test/unit/account_test.rb
|
15
|
+
ruby test/unit/account_test.rb -n /balance/
|
16
|
+
As a consequence, they work in RubyMate too (⌘R in TextMate).
|
17
|
+
|
18
|
+
<b>Note:</b> if the server is not started, tests fall back to running the usual way.
|
19
|
+
|
20
|
+
== Caveats
|
21
|
+
|
22
|
+
* There might exist some quirks: search for "TODO" in the source. I can bear them
|
23
|
+
but contributions are welcome.
|
24
|
+
* Some unit tests are left to be written.
|
25
|
+
|
26
|
+
== Credits
|
27
|
+
|
28
|
+
Written by {Roman Le Négrate}[http://roman.flucti.com] ({contact}[mailto:roman.lenegrate@gmail.com]). Released under the MIT license: see the +LICENSE+ file.
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
|
3
|
+
Echoe.new('rails-test-serving', '0.1.1') do |p|
|
4
|
+
p.description = "Makes unit tests of a Rails application run instantly"
|
5
|
+
p.url = "https://github.com/Roman2K/rails-test-serving"
|
6
|
+
p.author = "Roman Le Négrate"
|
7
|
+
p.email = "roman.lenegrate@gmail.com"
|
8
|
+
p.ignore_pattern = "*.gemspec"
|
9
|
+
p.development_dependencies = []
|
10
|
+
p.rdoc_options = %w(--main README.rdoc --inline-source --line-numbers --charset UTF-8)
|
11
|
+
end
|
@@ -0,0 +1,352 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'drb/unix'
|
4
|
+
require 'stringio'
|
5
|
+
require 'benchmark'
|
6
|
+
|
7
|
+
module RailsTestServing
|
8
|
+
class InvalidArgumentPattern < ArgumentError
|
9
|
+
end
|
10
|
+
class ServerUnavailable < StandardError
|
11
|
+
end
|
12
|
+
|
13
|
+
SERVICE_URI = "drbunix:tmp/sockets/test_server.sock"
|
14
|
+
|
15
|
+
def self.boot(argv=ARGV)
|
16
|
+
if argv.delete('--serve')
|
17
|
+
Server.start
|
18
|
+
elsif !argv.delete('--local')
|
19
|
+
Client.run_tests
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ConstantManagement
|
24
|
+
extend self
|
25
|
+
|
26
|
+
def legit?(const)
|
27
|
+
!const.to_s.empty? && constantize(const) == const
|
28
|
+
end
|
29
|
+
|
30
|
+
def constantize(name)
|
31
|
+
eval("#{name} if defined? #{name}", TOPLEVEL_BINDING)
|
32
|
+
end
|
33
|
+
|
34
|
+
def constantize!(name)
|
35
|
+
name.to_s.split('::').inject(Object) { |namespace, short| namespace.const_get(short) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# ActiveSupport's Module#remove_class doesn't behave quite the way I would expect it to.
|
39
|
+
def remove_constants(*names)
|
40
|
+
names.map do |name|
|
41
|
+
namespace, short = name.to_s =~ /^(.+)::(.+?)$/ ? [$1, $2] : ['Object', name]
|
42
|
+
constantize!(namespace).module_eval { remove_const(short) if const_defined?(short) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def subclasses_of(parent, options={})
|
47
|
+
children = []
|
48
|
+
ObjectSpace.each_object(Class) { |klass| children << klass if klass < parent && (!options[:legit] || legit?(klass)) }
|
49
|
+
children
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Client
|
54
|
+
extend self
|
55
|
+
|
56
|
+
# Setting this variable to true inhibits #run_tests.
|
57
|
+
@@disabled = false
|
58
|
+
|
59
|
+
def disable
|
60
|
+
@@disabled = true
|
61
|
+
yield
|
62
|
+
ensure
|
63
|
+
@@disabled = false
|
64
|
+
end
|
65
|
+
|
66
|
+
def tests_on_exit
|
67
|
+
!Test::Unit.run?
|
68
|
+
end
|
69
|
+
|
70
|
+
def tests_on_exit=(yes)
|
71
|
+
Test::Unit.run = !yes
|
72
|
+
end
|
73
|
+
|
74
|
+
def run_tests
|
75
|
+
return if @@disabled
|
76
|
+
run_tests!
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def run_tests!
|
82
|
+
handle_process_lifecycle do
|
83
|
+
server = DRbObject.new_with_uri(SERVICE_URI)
|
84
|
+
begin
|
85
|
+
puts(server.run($0, ARGV))
|
86
|
+
rescue DRb::DRbConnError
|
87
|
+
raise ServerUnavailable
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def handle_process_lifecycle
|
93
|
+
Client.tests_on_exit = false
|
94
|
+
begin
|
95
|
+
yield
|
96
|
+
rescue ServerUnavailable, InvalidArgumentPattern
|
97
|
+
Client.tests_on_exit = true
|
98
|
+
else
|
99
|
+
# TODO exit with a status code reflecting the result of the tests
|
100
|
+
exit 0
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Server
|
106
|
+
GUARD = Mutex.new
|
107
|
+
|
108
|
+
def self.start
|
109
|
+
DRb.start_service(SERVICE_URI, Server.new)
|
110
|
+
DRb.thread.join
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize
|
114
|
+
ENV['RAILS_ENV'] = 'test'
|
115
|
+
enable_dependency_tracking
|
116
|
+
start_cleaner
|
117
|
+
load_framework
|
118
|
+
|
119
|
+
log "** Test server started (##{$$})\n"
|
120
|
+
end
|
121
|
+
|
122
|
+
def run(file, argv)
|
123
|
+
GUARD.synchronize { perform_run(file, argv) }
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def log(message)
|
129
|
+
$stdout.print(message)
|
130
|
+
$stdout.flush
|
131
|
+
end
|
132
|
+
|
133
|
+
def shorten_path(path)
|
134
|
+
shortenable, base = File.expand_path(path), File.expand_path(Dir.pwd)
|
135
|
+
attempt = shortenable.sub(/^#{Regexp.escape base + File::SEPARATOR}/, '')
|
136
|
+
attempt.length < path.length ? attempt : path
|
137
|
+
end
|
138
|
+
|
139
|
+
def enable_dependency_tracking
|
140
|
+
require 'initializer'
|
141
|
+
|
142
|
+
Rails::Configuration.class_eval do
|
143
|
+
unless method_defined? :cache_classes
|
144
|
+
raise "#{self.class} out of sync with current Rails version"
|
145
|
+
end
|
146
|
+
|
147
|
+
def cache_classes
|
148
|
+
false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def start_cleaner
|
154
|
+
@cleaner = Cleaner.new
|
155
|
+
end
|
156
|
+
|
157
|
+
def load_framework
|
158
|
+
Client.disable { require 'test_helper' }
|
159
|
+
end
|
160
|
+
|
161
|
+
def perform_run(file, argv)
|
162
|
+
sanitize_arguments! file, argv
|
163
|
+
|
164
|
+
log ">> " + [shorten_path(file), *argv].join(' ')
|
165
|
+
|
166
|
+
result = nil
|
167
|
+
elapsed = Benchmark.realtime do
|
168
|
+
result = capture_test_result(file, argv)
|
169
|
+
end
|
170
|
+
log " (%d ms)\n" % (elapsed * 1000)
|
171
|
+
result
|
172
|
+
end
|
173
|
+
|
174
|
+
def sanitize_arguments!(file, argv)
|
175
|
+
if file =~ /^-/
|
176
|
+
# No file was specified for loading, only options. It's the case with
|
177
|
+
# Autotest.
|
178
|
+
raise InvalidArgumentPattern
|
179
|
+
end
|
180
|
+
|
181
|
+
# Filter out the junk that TextMate seems to inject into ARGV when running
|
182
|
+
# focused tests.
|
183
|
+
while a = find_index_by_pattern(argv, /^\[/) and z = find_index_by_pattern(argv[a..-1], /\]$/)
|
184
|
+
argv[a..a+z] = []
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def capture_test_result(file, argv)
|
189
|
+
result = []
|
190
|
+
@cleaner.clean_up_around do
|
191
|
+
result << capture_standard_stream('err') do
|
192
|
+
result << capture_standard_stream('out') do
|
193
|
+
result << capture_testrunner_result do
|
194
|
+
fix_objectspace_collector do
|
195
|
+
Client.disable { load(file) }
|
196
|
+
Test::Unit::AutoRunner.run(false, nil, argv)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
result.reverse.join
|
203
|
+
end
|
204
|
+
|
205
|
+
def capture_standard_stream(name)
|
206
|
+
eval("old, $std#{name} = $std#{name}, StringIO.new")
|
207
|
+
begin
|
208
|
+
yield
|
209
|
+
return eval("$std#{name}").string
|
210
|
+
ensure
|
211
|
+
eval("$std#{name} = old")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def capture_testrunner_result
|
216
|
+
set_default_testrunner_stream(io = StringIO.new) { yield }
|
217
|
+
io.string
|
218
|
+
end
|
219
|
+
|
220
|
+
# The default output stream of TestRunner is STDOUT which cannot be captured
|
221
|
+
# and, as a consequence, neither can TestRunner output when not instantiated
|
222
|
+
# explicitely. The following method can change the default output stream
|
223
|
+
# argument so that it can be set to a stream that can be captured instead.
|
224
|
+
def set_default_testrunner_stream(io)
|
225
|
+
require 'test/unit/ui/console/testrunner'
|
226
|
+
|
227
|
+
Test::Unit::UI::Console::TestRunner.class_eval do
|
228
|
+
alias_method :old_initialize, :initialize
|
229
|
+
def initialize(suite, output_level, io=Thread.current["test_runner_io"])
|
230
|
+
old_initialize(suite, output_level, io)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
Thread.current["test_runner_io"] = io
|
234
|
+
|
235
|
+
begin
|
236
|
+
return yield
|
237
|
+
ensure
|
238
|
+
Thread.current["test_runner_io"] = nil
|
239
|
+
Test::Unit::UI::Console::TestRunner.class_eval do
|
240
|
+
alias_method :initialize, :old_initialize
|
241
|
+
remove_method :old_initialize
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# The stock ObjectSpace collector collects every single class that inherits
|
247
|
+
# from Test::Unit, including those which have just been unassigned from
|
248
|
+
# their constant and not yet garbage collected. This method fixes that
|
249
|
+
# behaviour by filtering out these soon-to-be-garbage-collected classes.
|
250
|
+
def fix_objectspace_collector
|
251
|
+
require 'test/unit/collector/objectspace'
|
252
|
+
|
253
|
+
Test::Unit::Collector::ObjectSpace.class_eval do
|
254
|
+
alias_method :old_collect, :collect
|
255
|
+
def collect(name)
|
256
|
+
tests = []
|
257
|
+
ConstantManagement.subclasses_of(Test::Unit::TestCase, :legit => true).each { |klass| add_suite(tests, klass.suite) }
|
258
|
+
suite = Test::Unit::TestSuite.new(name)
|
259
|
+
sort(tests).each { |t| suite << t }
|
260
|
+
suite
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
begin
|
265
|
+
return yield
|
266
|
+
ensure
|
267
|
+
Test::Unit::Collector::ObjectSpace.class_eval do
|
268
|
+
alias_method :collect, :old_collect
|
269
|
+
remove_method :old_collect
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
private
|
275
|
+
|
276
|
+
def find_index_by_pattern(enumerable, pattern)
|
277
|
+
enumerable.each_with_index do |element, index|
|
278
|
+
return index if pattern === element
|
279
|
+
end
|
280
|
+
nil
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class Cleaner
|
285
|
+
include ConstantManagement
|
286
|
+
|
287
|
+
BREATH = 0.01
|
288
|
+
TESTCASE_CLASS_NAMES = %w( Test::Unit::TestCase
|
289
|
+
ActiveSupport::TestCase
|
290
|
+
ActionView::TestCase
|
291
|
+
ActionController::TestCase
|
292
|
+
ActionController::IntegrationTest
|
293
|
+
ActionMailer::TestCase )
|
294
|
+
|
295
|
+
def initialize
|
296
|
+
start_worker
|
297
|
+
end
|
298
|
+
|
299
|
+
def clean_up_around
|
300
|
+
check_worker_health
|
301
|
+
sleep BREATH while @working
|
302
|
+
begin
|
303
|
+
reload_app
|
304
|
+
yield
|
305
|
+
ensure
|
306
|
+
@working = true
|
307
|
+
sleep BREATH until @worker.stop?
|
308
|
+
@worker.wakeup
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
private
|
313
|
+
|
314
|
+
def start_worker
|
315
|
+
@worker = Thread.new do
|
316
|
+
Thread.abort_on_exception = true
|
317
|
+
loop do
|
318
|
+
Thread.stop
|
319
|
+
begin
|
320
|
+
clean_up_app
|
321
|
+
remove_tests
|
322
|
+
ensure
|
323
|
+
@working = false
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
@working = false
|
328
|
+
end
|
329
|
+
|
330
|
+
def check_worker_health
|
331
|
+
unless @worker.alive?
|
332
|
+
$stderr.puts "cleaning thread died, restarting"
|
333
|
+
start_worker
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def clean_up_app
|
338
|
+
ActionController::Dispatcher.new.cleanup_application
|
339
|
+
end
|
340
|
+
|
341
|
+
def remove_tests
|
342
|
+
TESTCASE_CLASS_NAMES.each do |name|
|
343
|
+
next unless klass = constantize(name)
|
344
|
+
remove_constants(*subclasses_of(klass).map { |c| c.to_s }.grep(/Test$/) - TESTCASE_CLASS_NAMES)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def reload_app
|
349
|
+
ActionController::Dispatcher.new.reload_application
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end unless defined? RailsTestServing
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Rails-test-serving-0.1.0
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
--- !ruby/object:Gem::Specification
|
6
|
+
name: rails-test-serving
|
7
|
+
version: !ruby/object:Gem::Version
|
8
|
+
version: 0.1.0
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- "Roman Le N\xC3\xA9grate"
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
|
15
|
+
date: 2008-11-16 00:00:00 +01:00
|
16
|
+
default_executable:
|
17
|
+
dependencies: []
|
18
|
+
|
19
|
+
description: Makes unit tests of a Rails application run instantly
|
20
|
+
email: roman.lenegrate@gmail.com
|
21
|
+
executables: []
|
22
|
+
|
23
|
+
extensions: []
|
24
|
+
|
25
|
+
extra_rdoc_files:
|
26
|
+
- lib/rails_test_serving.rb
|
27
|
+
- LICENSE
|
28
|
+
- README.rdoc
|
29
|
+
files:
|
30
|
+
- lib/rails_test_serving.rb
|
31
|
+
- LICENSE
|
32
|
+
- Manifest
|
33
|
+
- rails-test-serving.gemspec
|
34
|
+
- Rakefile
|
35
|
+
- README.rdoc
|
36
|
+
- test/rails_test_serving_test.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: https://github.com/Roman2K/rails-test-serving
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --main
|
42
|
+
- README.rdoc
|
43
|
+
- --inline-source
|
44
|
+
- --line-numbers
|
45
|
+
- --charset
|
46
|
+
- UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "1.2"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project: rails-test-serving
|
64
|
+
rubygems_version: 1.3.1
|
65
|
+
specification_version: 2
|
66
|
+
summary: Makes unit tests of a Rails application run instantly
|
67
|
+
test_files:
|
68
|
+
- test/rails_test_serving_test.rb
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'mocha'
|
3
|
+
Mocha::Configuration.prevent :stubbing_non_existent_method
|
4
|
+
Mocha::Configuration.warn_when :stubbing_method_unnecessarily
|
5
|
+
|
6
|
+
require 'rails_test_serving'
|
7
|
+
|
8
|
+
class RailsTestServingTest < Test::Unit::TestCase
|
9
|
+
include RailsTestServing
|
10
|
+
|
11
|
+
# class
|
12
|
+
|
13
|
+
def test_boot
|
14
|
+
argv = []
|
15
|
+
Client.expects(:run_tests)
|
16
|
+
RailsTestServing.boot(argv)
|
17
|
+
|
18
|
+
argv = ['--local']
|
19
|
+
Client.expects(:run_tests).never
|
20
|
+
RailsTestServing.boot(argv)
|
21
|
+
assert_equal [], argv
|
22
|
+
|
23
|
+
argv = ["--serve"]
|
24
|
+
Server.expects(:start)
|
25
|
+
RailsTestServing.boot(argv)
|
26
|
+
assert_equal [], argv
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class RailsTestServing::ConstantManagementTest < Test::Unit::TestCase
|
31
|
+
include RailsTestServing::ConstantManagement
|
32
|
+
NS = self
|
33
|
+
|
34
|
+
Foo = :foo
|
35
|
+
NamedFoo = Module.new
|
36
|
+
Namespace = Module.new
|
37
|
+
|
38
|
+
class A; end
|
39
|
+
class B < A; end
|
40
|
+
class C < B; end
|
41
|
+
|
42
|
+
def test_legit
|
43
|
+
assert legit?(NamedFoo)
|
44
|
+
|
45
|
+
assert !legit?("Inexistent")
|
46
|
+
|
47
|
+
fake = stub(:to_s => NamedFoo.to_s)
|
48
|
+
assert_equal NamedFoo.to_s, "#{fake}" # sanity check
|
49
|
+
assert !legit?(fake)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_constantize
|
53
|
+
assert_equal :foo, constantize("#{NS}::Foo")
|
54
|
+
assert_equal nil, constantize("#{NS}::Bar")
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_constantize!
|
58
|
+
assert_equal :foo, constantize!("#{NS}::Foo")
|
59
|
+
assert_raise(NameError) { constantize!("#{NS}::Bar") }
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_remove_constants
|
63
|
+
mod_A = Module.new
|
64
|
+
Namespace.const_set(:A, mod_A)
|
65
|
+
assert eval("defined? #{NS}::Namespace::A") # sanity check
|
66
|
+
|
67
|
+
removed = remove_constants("#{NS}::Namespace::A")
|
68
|
+
assert_equal [mod_A], removed
|
69
|
+
assert !eval("defined? #{NS}::Namespace::A")
|
70
|
+
|
71
|
+
removed = remove_constants("#{NS}::Namespace::A")
|
72
|
+
assert_equal [nil], removed
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_subclasses_of
|
76
|
+
assert_equal [C, B], subclasses_of(A)
|
77
|
+
assert_equal [C], subclasses_of(B)
|
78
|
+
assert_equal [], subclasses_of(C)
|
79
|
+
|
80
|
+
self.stubs(:legit?).with(B).returns true
|
81
|
+
self.stubs(:legit?).with(C).returns false
|
82
|
+
assert_equal [B], subclasses_of(A, :legit => true)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class RailsTestServing::ClientTest < Test::Unit::TestCase
|
87
|
+
C = RailsTestServing::Client
|
88
|
+
|
89
|
+
def test_run_tests
|
90
|
+
C.expects(:run_tests!)
|
91
|
+
C.run_tests
|
92
|
+
|
93
|
+
C.disable do
|
94
|
+
C.expects(:run_tests!).never
|
95
|
+
C.run_tests
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class RailsTestServing::ServerTest < Test::Unit::TestCase
|
101
|
+
|
102
|
+
# private
|
103
|
+
|
104
|
+
def test_perform_run
|
105
|
+
server = stub_server
|
106
|
+
file, argv = "test.rb", ["-n", "/pat/"]
|
107
|
+
|
108
|
+
server.stubs(:sanitize_arguments!)
|
109
|
+
Benchmark.stubs(:realtime).yields.returns 1
|
110
|
+
|
111
|
+
server.expects(:log).with(">> test.rb -n /pat/").once
|
112
|
+
server.stubs(:capture_test_result).with(file, argv).returns "result"
|
113
|
+
server.expects(:log).with(" (1000 ms)\n").once
|
114
|
+
|
115
|
+
result = server.instance_eval { perform_run(file, argv) }
|
116
|
+
assert_equal "result", result
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_sanitize_arguments
|
120
|
+
server = stub_server
|
121
|
+
sanitize = lambda { |*args| server.instance_eval { sanitize_arguments! *args } }
|
122
|
+
|
123
|
+
# valid
|
124
|
+
file, argv = "test.rb", ["--name=test_create"]
|
125
|
+
sanitize.call file, argv
|
126
|
+
|
127
|
+
assert_equal "test.rb", file
|
128
|
+
assert_equal ["--name=test_create"], argv
|
129
|
+
|
130
|
+
# TextMate junk
|
131
|
+
junk = ["[test_create,", "nil,", "nil]"]
|
132
|
+
|
133
|
+
# a) at the beginning
|
134
|
+
file, argv = "test.rb", junk + ["foo"]
|
135
|
+
sanitize.call file, argv
|
136
|
+
|
137
|
+
assert_equal "test.rb", file
|
138
|
+
assert_equal ["foo"], argv
|
139
|
+
|
140
|
+
# b) in between normal arguments
|
141
|
+
file, argv = "test.rb", ["foo"] + junk + ["bar"]
|
142
|
+
sanitize.call file, argv
|
143
|
+
|
144
|
+
assert_equal "test.rb", file
|
145
|
+
assert_equal ["foo", "bar"], argv
|
146
|
+
|
147
|
+
# invalid arguments
|
148
|
+
assert_raise RailsTestServing::InvalidArgumentPattern do
|
149
|
+
sanitize.call "-e", ["code"]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_shorten_path
|
154
|
+
server = stub_server
|
155
|
+
Dir.stubs(:pwd).returns '/base'
|
156
|
+
|
157
|
+
assert_equal 'test.rb', server.instance_eval { shorten_path 'test.rb' }
|
158
|
+
assert_equal 'test.rb', server.instance_eval { shorten_path '/base/test.rb' }
|
159
|
+
assert_equal '/other-base/test.rb', server.instance_eval { shorten_path '/other-base/test.rb' }
|
160
|
+
assert_equal '/other-base/test.rb', server.instance_eval { shorten_path '/other-base/././test.rb' }
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_capture_test_result
|
164
|
+
server = stub_server
|
165
|
+
cleaner = server.instance_variable_set(:@cleaner, stub)
|
166
|
+
|
167
|
+
cleaner.stubs(:clean_up_around).yields
|
168
|
+
server.stubs(:capture_standard_stream).with('err').yields.returns "stderr"
|
169
|
+
server.stubs(:capture_standard_stream).with('out').yields.returns "stdout"
|
170
|
+
server.stubs(:capture_testrunner_result).yields.returns "result"
|
171
|
+
server.stubs(:fix_objectspace_collector).yields
|
172
|
+
|
173
|
+
server.stubs(:load).with("file")
|
174
|
+
Test::Unit::AutoRunner.expects(:run).with(false, nil, "argv")
|
175
|
+
|
176
|
+
result = server.instance_eval { capture_test_result("file", "argv") }
|
177
|
+
assert_equal "stderrstdoutresult", result
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_capture_standard_stream
|
181
|
+
server = stub_server
|
182
|
+
assert_equal STDOUT, $stdout # sanity check
|
183
|
+
|
184
|
+
captured = server.instance_eval { capture_standard_stream('out') { print "test" } }
|
185
|
+
|
186
|
+
assert_equal "test", captured
|
187
|
+
assert_equal STDOUT, $stdout
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_capture_testrunner_result
|
191
|
+
server = stub_server
|
192
|
+
|
193
|
+
captured = server.instance_eval do
|
194
|
+
capture_testrunner_result { Thread.current["test_runner_io"].print "test" }
|
195
|
+
end
|
196
|
+
|
197
|
+
assert_equal "test", captured
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
S = RailsTestServing::Server
|
203
|
+
|
204
|
+
def stub_server
|
205
|
+
S.any_instance.stubs(:enable_dependency_tracking)
|
206
|
+
S.any_instance.stubs(:start_cleaner)
|
207
|
+
S.any_instance.stubs(:load_framework)
|
208
|
+
S.any_instance.stubs(:log)
|
209
|
+
S.new
|
210
|
+
end
|
211
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Roman2K-rails-test-serving
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Roman Le N\xC3\xA9grate"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
date: 2008-11-15 15:00:00 -08:00
|
12
|
+
default_executable:
|
13
|
+
dependencies: []
|
14
|
+
|
15
|
+
description: Makes unit tests of a Rails application run instantly
|
16
|
+
email: roman.lenegrate@gmail.com
|
17
|
+
executables: []
|
18
|
+
|
19
|
+
extensions: []
|
20
|
+
|
21
|
+
extra_rdoc_files:
|
22
|
+
- lib/rails_test_serving.rb
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- lib/rails_test_serving.rb
|
27
|
+
- LICENSE
|
28
|
+
- Manifest
|
29
|
+
- rails-test-serving.gemspec
|
30
|
+
- Rakefile
|
31
|
+
- README.rdoc
|
32
|
+
- test/rails_test_serving_test.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: https://github.com/Roman2K/rails-test-serving
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --main
|
38
|
+
- README.rdoc
|
39
|
+
- --inline-source
|
40
|
+
- --line-numbers
|
41
|
+
- --charset
|
42
|
+
- UTF-8
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "1.2"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project: rails-test-serving
|
60
|
+
rubygems_version: 1.2.0
|
61
|
+
signing_key:
|
62
|
+
specification_version: 2
|
63
|
+
summary: Makes unit tests of a Rails application run instantly
|
64
|
+
test_files:
|
65
|
+
- test/rails_test_serving_test.rb
|