rails-test-serving 0.1.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2008-2009 Roman Le Négrate
2
+
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:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
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.
@@ -0,0 +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
7
+ lib/rails_test_serving.rb
8
+ LICENSE
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
@@ -0,0 +1,79 @@
1
+ # RailsTestServing
2
+
3
+ Tired of waiting 10 seconds before your tests run? `RailsTestServing` can make them run almost instantly. This library is described more thoroughly in its [introduction article](http://roman.flucti.com/a-test-server-for-rails-applications).
4
+
5
+ ## Usage
6
+
7
+ 1. Install the gem:
8
+
9
+ gem install Roman2K-rails-test-serving -s http://gems.github.com
10
+
11
+ 2. Insert the following lines at the very top of `test/test_helper.rb`:
12
+
13
+ require 'rubygems'
14
+ require 'rails_test_serving'
15
+ RailsTestServing.boot
16
+
17
+ 3. Append the following line to `~/.bash_profile`:
18
+
19
+ export RUBYLIB=".:test:$RUBYLIB"
20
+
21
+ If you get loading errors during the next steps:
22
+ * Move the `RUBYLIB` line from `~/.bash_profile` to `~/.bash_login` instead.
23
+ * 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).
24
+
25
+ 4. Start the server:
26
+
27
+ cd <project-dir>
28
+ ruby test/test_helper.rb --serve
29
+
30
+ 5. Run tests as you usually do:
31
+
32
+ ruby test/unit/account_test.rb
33
+ ruby test/unit/account_test.rb -n /balance/
34
+
35
+ As a consequence, they work in RubyMate too (⌘R in TextMate).
36
+
37
+ 6. Have a lot a models and/or mixins? You can reduce reloading time to almost nothing by using `RailsTestServing` in combination with [RailsDevelopmentBoost](https://github.com/Roman2K/rails-dev-boost). Since was originally intended to speed up web-browsing in development mode, be sure to read the note in the `README` for how to enable it in test mode.
38
+
39
+ **Note:** if the server is not started, tests fall back to running the usual way.
40
+
41
+ ## Options
42
+
43
+ An option hash can be specified for `RailsTestServing` to use, by defining `$test_server_options` right before `require 'rails_test_serving'`. It must be a hash with symbol keys. Currently available options are:
44
+
45
+ * `reload`: An array of regular expressions (or any object responding to `===`) 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 kept around before being re-`require`'d.
46
+
47
+ Example `test_helper.rb` head:
48
+
49
+ require 'rubygems'
50
+
51
+ $test_server_options = { :reload => [/blueprint/] }
52
+ require 'rails_test_serving'
53
+ RailsTestServing.boot
54
+
55
+ # ...remainder here...
56
+
57
+ When running tests from the command line, you can bypass the server, forcing tests to be run locally, by passing the `--local` flag. For example:
58
+
59
+ ruby test/unit/account_test.rb --local
60
+
61
+ ## Caveats
62
+
63
+ * Tested working with Rails 2.1.2 up to 2.2.2. Compatibility with versions of Rails out of that range is not guaranteed.
64
+ * There might exist some quirks: search for "TODO" in the source. I can bear them but contributions are welcome.
65
+ * Some unit tests are left to be written.
66
+
67
+ ## Credits
68
+
69
+ Code:
70
+
71
+ * [Roman Le Négrate](http://roman.flucti.com), a.k.a. Roman2K ([contact](mailto:roman.lenegrate@gmail.com))
72
+ * [Jack Chen](http://github.com/chendo), a.k.a. chendo
73
+
74
+ Feedback:
75
+
76
+ * Justin Ko
77
+ * [Dr Nic Williams](http://drnicwilliams.com)
78
+
79
+ Released under the MIT license: see the `LICENSE` file.
@@ -0,0 +1,11 @@
1
+ require 'echoe'
2
+
3
+ Echoe.new('rails-test-serving', '0.1.4.2') 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.mdown --inline-source --line-numbers --charset UTF-8)
11
+ end
@@ -0,0 +1,22 @@
1
+ require 'pathname'
2
+ require 'thread'
3
+ require 'test/unit'
4
+ require 'drb/unix'
5
+ require 'stringio'
6
+ require 'benchmark'
7
+
8
+ module RailsTestServing
9
+ class InvalidArgumentPattern < ArgumentError
10
+ end
11
+ class ServerUnavailable < StandardError
12
+ end
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
@@ -0,0 +1,58 @@
1
+ module RailsTestServing
2
+ module Bootstrap
3
+ SOCKET_PATH = ['tmp', 'sockets', 'test_server.sock']
4
+
5
+ def boot(argv=ARGV)
6
+ if argv.delete('--serve')
7
+ start_server
8
+ elsif !argv.delete('--local')
9
+ Client.run_tests
10
+ end
11
+ end
12
+
13
+ def service_uri
14
+ @service_uri ||= begin
15
+ # Determine RAILS_ROOT
16
+ root, max_depth = Pathname('.'), Pathname.pwd.expand_path.to_s.split(File::SEPARATOR).size
17
+ until root.join('config', 'boot.rb').file?
18
+ root = root.parent
19
+ if root.to_s.split(File::SEPARATOR).size >= max_depth
20
+ raise "RAILS_ROOT could not be determined"
21
+ end
22
+ end
23
+ root = root.cleanpath
24
+
25
+ # Adjust load path
26
+ $: << root.to_s << root.join('test').to_s
27
+
28
+ # Ensure socket directory exists
29
+ path = root.join(*SOCKET_PATH)
30
+ path.dirname.mkpath
31
+
32
+ # URI
33
+ "drbunix:#{path}"
34
+ end
35
+ end
36
+
37
+ def options
38
+ @options ||= begin
39
+ options = $test_server_options || {}
40
+ options[:reload] ||= []
41
+ options
42
+ end
43
+ end
44
+
45
+ def active?
46
+ @active
47
+ end
48
+
49
+ private
50
+
51
+ def start_server
52
+ @active = true
53
+ Server.start
54
+ ensure
55
+ @active = false
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,103 @@
1
+ module RailsTestServing
2
+ class Cleaner
3
+ include ConstantManagement
4
+
5
+ PAUSE = 0.01
6
+ TESTCASE_CLASS_NAMES = %w( Test::Unit::TestCase
7
+ ActiveSupport::TestCase
8
+ ActionView::TestCase
9
+ ActionController::TestCase
10
+ ActionController::IntegrationTest
11
+ ActionMailer::TestCase )
12
+
13
+ def initialize
14
+ start_worker
15
+ end
16
+
17
+ def clean_up_around
18
+ check_worker_health
19
+ sleep PAUSE while @working
20
+ begin
21
+ reload_app
22
+ yield
23
+ ensure
24
+ @working = true
25
+ sleep PAUSE until @worker.stop?
26
+ @worker.wakeup
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def start_worker
33
+ @worker = Thread.new do
34
+ Thread.abort_on_exception = true
35
+ loop do
36
+ Thread.stop
37
+ begin
38
+ clean_up_app
39
+ remove_tests
40
+ ensure
41
+ @working = false
42
+ end
43
+ end
44
+ end
45
+ @working = false
46
+ end
47
+
48
+ def check_worker_health
49
+ unless @worker.alive?
50
+ $stderr.puts "cleaning thread died, restarting"
51
+ start_worker
52
+ end
53
+ end
54
+
55
+ def clean_up_app
56
+ if ActionController::Dispatcher.respond_to?(:cleanup_application)
57
+ ActionController::Dispatcher.cleanup_application
58
+ else
59
+ ActionController::Dispatcher.new(StringIO.new).cleanup_application
60
+ end
61
+ if defined?(Fixtures) && Fixtures.respond_to?(:reset_cache)
62
+ Fixtures.reset_cache
63
+ end
64
+
65
+ # Reload files that match :reload here instead of in reload_app since the
66
+ # :reload option is intended to target files that don't change between two
67
+ # consecutive runs (an external library for example). That way, they are
68
+ # reloaded in the background instead of slowing down the next run.
69
+ reload_specified_source_files
70
+ end
71
+
72
+ def remove_tests
73
+ TESTCASE_CLASS_NAMES.each do |name|
74
+ next unless klass = constantize(name)
75
+ remove_constants(*subclasses_of(klass).map { |c| c.to_s }.grep(/Test$/) - TESTCASE_CLASS_NAMES)
76
+ end
77
+ end
78
+
79
+ def reload_app
80
+ if ActionController::Dispatcher.respond_to?(:reload_application)
81
+ ActionController::Dispatcher.reload_application
82
+ else
83
+ ActionController::Dispatcher.new(StringIO.new).reload_application
84
+ end
85
+ end
86
+
87
+ def reload_specified_source_files
88
+ to_reload =
89
+ $".select do |path|
90
+ RailsTestServing.options[:reload].any? do |matcher|
91
+ matcher === path
92
+ end
93
+ end
94
+
95
+ # Force a reload by removing matched files from $"
96
+ $".replace($" - to_reload)
97
+
98
+ to_reload.each do |file|
99
+ require file
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,53 @@
1
+ module RailsTestServing
2
+ module Client
3
+ extend self
4
+
5
+ # Setting this variable to true inhibits #run_tests.
6
+ @@disabled = false
7
+
8
+ def disable
9
+ @@disabled = true
10
+ yield
11
+ ensure
12
+ @@disabled = false
13
+ end
14
+
15
+ def tests_on_exit
16
+ !Test::Unit.run?
17
+ end
18
+
19
+ def tests_on_exit=(yes)
20
+ Test::Unit.run = !yes
21
+ end
22
+
23
+ def run_tests
24
+ return if @@disabled
25
+ run_tests!
26
+ end
27
+
28
+ private
29
+
30
+ def run_tests!
31
+ handle_process_lifecycle do
32
+ server = DRbObject.new_with_uri(RailsTestServing.service_uri)
33
+ begin
34
+ puts(server.run($0, ARGV))
35
+ rescue DRb::DRbConnError
36
+ raise ServerUnavailable
37
+ end
38
+ end
39
+ end
40
+
41
+ def handle_process_lifecycle
42
+ Client.tests_on_exit = false
43
+ begin
44
+ yield
45
+ rescue ServerUnavailable, InvalidArgumentPattern
46
+ Client.tests_on_exit = true
47
+ else
48
+ # TODO exit with a status code reflecting the result of the tests
49
+ exit 0
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,31 @@
1
+ module RailsTestServing
2
+ module ConstantManagement
3
+ extend self
4
+
5
+ def legit?(const)
6
+ !const.to_s.empty? && constantize(const) == const
7
+ end
8
+
9
+ def constantize(name)
10
+ eval("#{name} if defined? #{name}", TOPLEVEL_BINDING)
11
+ end
12
+
13
+ def constantize!(name)
14
+ name.to_s.split('::').inject(Object) { |namespace, short| namespace.const_get(short) }
15
+ end
16
+
17
+ # ActiveSupport's Module#remove_class doesn't behave quite the way I would expect it to.
18
+ def remove_constants(*names)
19
+ names.map do |name|
20
+ namespace, short = name.to_s =~ /^(.+)::(.+?)$/ ? [$1, $2] : ['Object', name]
21
+ constantize!(namespace).module_eval { remove_const(short) if const_defined?(short) }
22
+ end
23
+ end
24
+
25
+ def subclasses_of(parent, options={})
26
+ children = []
27
+ ObjectSpace.each_object(Class) { |klass| children << klass if klass < parent && (!options[:legit] || legit?(klass)) }
28
+ children
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,131 @@
1
+ module RailsTestServing
2
+ class Server
3
+ GUARD = Mutex.new
4
+ PREPARATION_GUARD = Mutex.new
5
+
6
+ def self.start
7
+ server = Server.new
8
+ DRb.start_service(RailsTestServing.service_uri, server)
9
+ Thread.new { server.prepare }
10
+ DRb.thread.join
11
+ end
12
+
13
+ include Utilities
14
+
15
+ def run(file, argv)
16
+ GUARD.synchronize do
17
+ prepare
18
+ perform_run(file, argv)
19
+ end
20
+ end
21
+
22
+ def prepare
23
+ PREPARATION_GUARD.synchronize do
24
+ @prepared ||= begin
25
+ ENV['RAILS_ENV'] = 'test'
26
+ log "** Test server starting [##{$$}]..." do
27
+ enable_dependency_tracking
28
+ start_cleaner
29
+ load_framework
30
+ end
31
+ install_signal_traps
32
+ true
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def enable_dependency_tracking
40
+ require 'config/boot'
41
+
42
+ Rails::Configuration.class_eval do
43
+ unless method_defined? :cache_classes
44
+ raise "#{self.class} out of sync with current Rails version"
45
+ end
46
+
47
+ def cache_classes
48
+ false
49
+ end
50
+ end
51
+ end
52
+
53
+ def start_cleaner
54
+ @cleaner = Cleaner.new
55
+ end
56
+
57
+ def load_framework
58
+ Client.disable do
59
+ $: << 'test'
60
+ require 'test_helper'
61
+ end
62
+ end
63
+
64
+ def install_signal_traps
65
+ log " - CTRL+C: Stop the server\n"
66
+ trap(:INT) do
67
+ GUARD.synchronize do
68
+ log "** Stopping the server..." do
69
+ DRb.thread.raise Interrupt, "stop"
70
+ end
71
+ end
72
+ end
73
+
74
+ log " - CTRL+Z: Reset database column information cache\n"
75
+ trap(:TSTP) do
76
+ GUARD.synchronize do
77
+ log "** Resetting database column information cache..." do
78
+ ActiveRecord::Base.instance_eval { subclasses }.each { |c| c.reset_column_information }
79
+ end
80
+ end
81
+ end
82
+
83
+ log " - CTRL+`: Reset lazy-loaded constants\n"
84
+ trap(:QUIT) do
85
+ GUARD.synchronize do
86
+ log "** Resetting lazy-loaded constants..." do
87
+ (defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : Dependencies).clear
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def perform_run(file, argv)
94
+ sanitize_arguments!(file, argv)
95
+ log ">> " + [shorten_path(file), *argv].join(' ') do
96
+ capture_test_result(file, argv)
97
+ end
98
+ end
99
+
100
+ def sanitize_arguments!(file, argv)
101
+ if file =~ /^-/
102
+ # No file was specified for loading, only options. It's the case with
103
+ # Autotest.
104
+ raise InvalidArgumentPattern
105
+ end
106
+
107
+ # Filter out the junk that TextMate seems to inject into ARGV when running
108
+ # focused tests.
109
+ while a = find_index_by_pattern(argv, /^\[/) and z = find_index_by_pattern(argv[a..-1], /\]$/)
110
+ argv[a..a+z] = []
111
+ end
112
+ end
113
+
114
+ def capture_test_result(file, argv)
115
+ result = []
116
+ @cleaner.clean_up_around do
117
+ result << capture_standard_stream('err') do
118
+ result << capture_standard_stream('out') do
119
+ result << capture_testrunner_result do
120
+ fix_objectspace_collector do
121
+ Client.disable { load(file) }
122
+ Test::Unit::AutoRunner.run(false, nil, argv)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ result.reverse.join
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,102 @@
1
+ module RailsTestServing
2
+ module Utilities
3
+ def log(message, stream=$stdout)
4
+ print = lambda do |str|
5
+ stream.print(str)
6
+ stream.flush
7
+ end
8
+
9
+ print[message]
10
+ if block_given?
11
+ result = nil
12
+ elapsed = Benchmark.realtime do
13
+ result = yield
14
+ end
15
+ print[" (%d ms)\n" % (elapsed * 1000)]
16
+ result
17
+ end
18
+ end
19
+
20
+ def capture_standard_stream(name)
21
+ eval("old, $std#{name} = $std#{name}, StringIO.new")
22
+ begin
23
+ yield
24
+ return eval("$std#{name}").string
25
+ ensure
26
+ eval("$std#{name} = old")
27
+ end
28
+ end
29
+
30
+ def capture_testrunner_result
31
+ set_default_testrunner_stream(io = StringIO.new) { yield }
32
+ io.string
33
+ end
34
+
35
+ # The default output stream of TestRunner is STDOUT which cannot be captured
36
+ # and, as a consequence, neither can TestRunner output when not instantiated
37
+ # explicitely. The following method can change the default output stream
38
+ # argument so that it can be set to a stream that can be captured instead.
39
+ def set_default_testrunner_stream(io)
40
+ require 'test/unit/ui/console/testrunner'
41
+
42
+ Test::Unit::UI::Console::TestRunner.class_eval do
43
+ alias_method :old_initialize, :initialize
44
+ def initialize(suite, output_level, io=Thread.current["test_runner_io"])
45
+ old_initialize(suite, output_level, io)
46
+ end
47
+ end
48
+ Thread.current["test_runner_io"] = io
49
+
50
+ begin
51
+ return yield
52
+ ensure
53
+ Thread.current["test_runner_io"] = nil
54
+ Test::Unit::UI::Console::TestRunner.class_eval do
55
+ alias_method :initialize, :old_initialize
56
+ remove_method :old_initialize
57
+ end
58
+ end
59
+ end
60
+
61
+ # The stock ObjectSpace collector collects every single class that inherits
62
+ # from Test::Unit, including those which have just been unassigned from
63
+ # their constant and not yet garbage collected. This method fixes that
64
+ # behaviour by filtering out these soon-to-be-garbage-collected classes.
65
+ def fix_objectspace_collector
66
+ require 'test/unit/collector/objectspace'
67
+
68
+ Test::Unit::Collector::ObjectSpace.class_eval do
69
+ alias_method :old_collect, :collect
70
+ def collect(name)
71
+ tests = []
72
+ ConstantManagement.subclasses_of(Test::Unit::TestCase, :legit => true).each { |klass| add_suite(tests, klass.suite) }
73
+ suite = Test::Unit::TestSuite.new(name)
74
+ sort(tests).each { |t| suite << t }
75
+ suite
76
+ end
77
+ end
78
+
79
+ begin
80
+ return yield
81
+ ensure
82
+ Test::Unit::Collector::ObjectSpace.class_eval do
83
+ alias_method :collect, :old_collect
84
+ remove_method :old_collect
85
+ end
86
+ end
87
+ end
88
+
89
+ def shorten_path(path)
90
+ shortenable, base = File.expand_path(path), File.expand_path(Dir.pwd)
91
+ attempt = shortenable.sub(/^#{Regexp.escape base + File::SEPARATOR}/, '')
92
+ attempt.length < path.length ? attempt : path
93
+ end
94
+
95
+ def find_index_by_pattern(enumerable, pattern)
96
+ enumerable.each_with_index do |element, index|
97
+ return index if pattern === element
98
+ end
99
+ nil
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rails-test-serving}
5
+ s.version = "0.1.4.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Roman Le N\303\251grate"]
9
+ s.date = %q{2009-04-20}
10
+ s.description = %q{Makes unit tests of a Rails application run instantly}
11
+ s.email = %q{roman.lenegrate@gmail.com}
12
+ s.extra_rdoc_files = ["lib/rails_test_serving/bootstrap.rb", "lib/rails_test_serving/cleaner.rb", "lib/rails_test_serving/client.rb", "lib/rails_test_serving/constant_management.rb", "lib/rails_test_serving/server.rb", "lib/rails_test_serving/utilities.rb", "lib/rails_test_serving.rb", "LICENSE", "README.mdown"]
13
+ s.files = ["lib/rails_test_serving/bootstrap.rb", "lib/rails_test_serving/cleaner.rb", "lib/rails_test_serving/client.rb", "lib/rails_test_serving/constant_management.rb", "lib/rails_test_serving/server.rb", "lib/rails_test_serving/utilities.rb", "lib/rails_test_serving.rb", "LICENSE", "Manifest", "Rakefile", "README.mdown", "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", "rails-test-serving.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{https://github.com/Roman2K/rails-test-serving}
16
+ s.rdoc_options = ["--main", "README.mdown", "--inline-source", "--line-numbers", "--charset", "UTF-8"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{rails-test-serving}
19
+ s.rubygems_version = %q{1.3.2}
20
+ s.summary = %q{Makes unit tests of a Rails application run instantly}
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
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ else
29
+ end
30
+ else
31
+ end
32
+ end
@@ -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 ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-test-serving
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4.2
5
+ platform: ruby
6
+ authors:
7
+ - "Roman Le N\xC3\xA9grate"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-20 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Makes unit tests of a Rails application run instantly
17
+ email: roman.lenegrate@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - lib/rails_test_serving/bootstrap.rb
24
+ - lib/rails_test_serving/cleaner.rb
25
+ - lib/rails_test_serving/client.rb
26
+ - lib/rails_test_serving/constant_management.rb
27
+ - lib/rails_test_serving/server.rb
28
+ - lib/rails_test_serving/utilities.rb
29
+ - lib/rails_test_serving.rb
30
+ - LICENSE
31
+ - README.mdown
32
+ files:
33
+ - lib/rails_test_serving/bootstrap.rb
34
+ - lib/rails_test_serving/cleaner.rb
35
+ - lib/rails_test_serving/client.rb
36
+ - lib/rails_test_serving/constant_management.rb
37
+ - lib/rails_test_serving/server.rb
38
+ - lib/rails_test_serving/utilities.rb
39
+ - lib/rails_test_serving.rb
40
+ - LICENSE
41
+ - Manifest
42
+ - Rakefile
43
+ - README.mdown
44
+ - test/rails_test_serving/bootstrap_test.rb
45
+ - test/rails_test_serving/cleaner_test.rb
46
+ - test/rails_test_serving/client_test.rb
47
+ - test/rails_test_serving/constant_management_test.rb
48
+ - test/rails_test_serving/server_test.rb
49
+ - test/rails_test_serving/utilities_test.rb
50
+ - test/test_helper.rb
51
+ - rails-test-serving.gemspec
52
+ has_rdoc: true
53
+ homepage: https://github.com/Roman2K/rails-test-serving
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --main
59
+ - README.mdown
60
+ - --inline-source
61
+ - --line-numbers
62
+ - --charset
63
+ - UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "1.2"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project: rails-test-serving
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Makes unit tests of a Rails application run instantly
85
+ test_files:
86
+ - test/rails_test_serving/bootstrap_test.rb
87
+ - test/rails_test_serving/cleaner_test.rb
88
+ - test/rails_test_serving/client_test.rb
89
+ - test/rails_test_serving/constant_management_test.rb
90
+ - test/rails_test_serving/server_test.rb
91
+ - test/rails_test_serving/utilities_test.rb
92
+ - test/test_helper.rb