zeus-justinf 0.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ module Zeus
2
+ module M
3
+ ### Simple data structure for what a test method contains.
4
+ #
5
+ # Too lazy to make a class for this when it's really just a bag of data
6
+ # without any behavior.
7
+ #
8
+ # Includes the name of this method, what line on the file it begins on,
9
+ # and where it ends.
10
+ class TestMethod < Struct.new(:name, :start_line, :end_line)
11
+ # Set up a new test method for this test suite class
12
+ def self.create(suite_class, test_method, find_locations = true)
13
+ # Hopefully it's been defined as an instance method, so we'll need to
14
+ # look up the ruby Method instance for it
15
+ method = suite_class.instance_method(test_method)
16
+
17
+ if find_locations
18
+ # Ruby can find the starting line for us, so pull that out of the array
19
+ start_line = method.source_location.last
20
+
21
+ # Ruby can't find the end line however, and I'm too lazy to write
22
+ # a parser. Instead, `method_source` adds `Method#source` so we can
23
+ # deduce this ourselves.
24
+ #
25
+ # The end line should be the number of line breaks in the method source,
26
+ # added to the starting line and subtracted by one.
27
+ end_line = method.source.split("\n").size + start_line - 1
28
+ end
29
+
30
+ # Shove the given attributes into a new databag
31
+ new(test_method, start_line, end_line)
32
+ end
33
+
34
+ def escaped_name
35
+ Regexp.escape(name)
36
+ end
37
+ end
38
+ end
39
+ end
data/lib/zeus/plan.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Zeus
2
+ class Plan
3
+ def after_fork ; end
4
+ end
5
+ end
6
+
data/lib/zeus/rails.rb ADDED
@@ -0,0 +1,256 @@
1
+ def find_rails_path(root_path)
2
+ paths = %w(spec/dummy test/dummy .)
3
+ paths.find { |path| File.exists?(File.expand_path(path, root_path)) }
4
+ end
5
+
6
+ ROOT_PATH = File.expand_path(Dir.pwd)
7
+ RAILS_PATH = find_rails_path(ROOT_PATH)
8
+ ENV_PATH = File.expand_path('config/environment', RAILS_PATH)
9
+ BOOT_PATH = File.expand_path('config/boot', RAILS_PATH)
10
+ APP_PATH = File.expand_path('config/application', RAILS_PATH) unless defined? APP_PATH
11
+
12
+ require 'zeus'
13
+
14
+ def gem_is_bundled?(gem)
15
+ gemfile_lock_contents = File.read(ROOT_PATH + "/Gemfile.lock")
16
+ gemfile_lock_contents.scan(/^\s*#{gem} \(([^=~><]+?)\)/).flatten.first
17
+ end
18
+
19
+ if version = gem_is_bundled?('method_source')
20
+ gem 'method_source', version
21
+ end
22
+
23
+ require 'zeus/m'
24
+
25
+ module Zeus
26
+ class Rails < Plan
27
+ def after_fork
28
+ reconnect_activerecord
29
+ restart_girl_friday
30
+ reconnect_redis
31
+ end
32
+
33
+ def _monkeypatch_rake
34
+ if version = gem_is_bundled?('rake')
35
+ gem 'rake', version
36
+ end
37
+ require 'rake/testtask'
38
+ Rake::TestTask.class_eval {
39
+
40
+ # Create the tasks defined by this task lib.
41
+ def define
42
+ desc "Run tests" + (@name==:test ? "" : " for #{@name}")
43
+ task @name do
44
+ # ruby "#{ruby_opts_string} #{run_code} #{file_list_string} #{option_list}"
45
+ rails_env = ENV['RAILS_ENV']
46
+ rubyopt = ENV['RUBYOPT']
47
+ ENV['RAILS_ENV'] = nil
48
+ ENV['RUBYOPT'] = nil # bundler sets this to require bundler :|
49
+ puts "zeus test #{file_list_string}"
50
+ ret = system "zeus test #{file_list_string}"
51
+ ENV['RAILS_ENV'] = rails_env
52
+ ENV['RUBYOPT'] = rubyopt
53
+ ret
54
+ end
55
+ self
56
+ end
57
+
58
+ alias_method :_original_define, :define
59
+
60
+ def self.inherited(klass)
61
+ return unless klass.name == "TestTaskWithoutDescription"
62
+ klass.class_eval {
63
+ def self.method_added(sym)
64
+ class_eval do
65
+ if !@rails_hack_reversed
66
+ @rails_hack_reversed = true
67
+ alias_method :define, :_original_define
68
+ def desc(*)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ }
74
+ end
75
+ }
76
+ end
77
+
78
+ def boot
79
+ _monkeypatch_rake
80
+ $LOAD_PATH.unshift "./lib"
81
+
82
+ require BOOT_PATH
83
+ # config/application.rb normally requires 'rails/all'.
84
+ # Some 'alternative' ORMs such as Mongoid give instructions to switch this require
85
+ # out for a list of railties, not including ActiveRecord.
86
+ # We grep config/application.rb for all requires of rails/all or railties, and require them.
87
+ rails_components = File.read(APP_PATH + ".rb").
88
+ scan(/^\s*require\s*['"](.*railtie.*|rails\/all)['"]/).flatten
89
+
90
+ rails_components = ["rails/all"] if rails_components == []
91
+ rails_components.each do |component|
92
+ require component
93
+ end
94
+ end
95
+
96
+ def default_bundle
97
+ Bundler.require(:default)
98
+ Zeus::LoadTracking.add_feature('./Gemfile.lock')
99
+ end
100
+
101
+ def development_environment
102
+ Bundler.require(:development)
103
+ ::Rails.env = ENV['RAILS_ENV'] = "development"
104
+ require APP_PATH
105
+ ::Rails.application.require_environment!
106
+ end
107
+
108
+ def prerake
109
+ require 'rake'
110
+ end
111
+
112
+ def rake
113
+ Rake.application.run
114
+ end
115
+
116
+ def generate
117
+ load_rails_generators
118
+ require 'rails/commands/generate'
119
+ end
120
+
121
+ def destroy
122
+ load_rails_generators
123
+ require 'rails/commands/destroy'
124
+ end
125
+
126
+ def runner
127
+ require 'rails/commands/runner'
128
+ end
129
+
130
+ def console
131
+ if defined?(Pry) && IRB == Pry
132
+ require "pry"
133
+ Pry.start
134
+ else
135
+ require 'rails/commands/console'
136
+ ::Rails::Console.start(::Rails.application)
137
+ end
138
+ end
139
+
140
+ def dbconsole
141
+ require 'rails/commands/dbconsole'
142
+
143
+ meth = ::Rails::DBConsole.method(:start)
144
+
145
+ # `Rails::DBConsole.start` has been changed to load faster in
146
+ # https://github.com/rails/rails/commit/346bb018499cde6699fcce6c68dd7e9be45c75e1
147
+ #
148
+ # This will work with both versions.
149
+ if meth.arity.zero?
150
+ ::Rails::DBConsole.start
151
+ else
152
+ ::Rails::DBConsole.start(::Rails.application)
153
+ end
154
+ end
155
+
156
+ def server
157
+ require 'rails/commands/server'
158
+ server = ::Rails::Server.new
159
+ Dir.chdir(::Rails.application.root)
160
+ server.start
161
+ end
162
+
163
+ def test_environment
164
+ Bundler.require(:test)
165
+
166
+ ::Rails.env = ENV['RAILS_ENV'] = 'test'
167
+ require APP_PATH
168
+
169
+ $rails_rake_task = 'yup' # lie to skip eager loading
170
+ ::Rails.application.require_environment!
171
+ $rails_rake_task = nil
172
+
173
+ $LOAD_PATH.unshift ".", "./lib", "./test", "./spec"
174
+ end
175
+
176
+ def test_helper
177
+ # don't let minitest setup another exit hook
178
+ begin
179
+ require 'minitest/unit'
180
+ MiniTest::Unit.class_variable_set("@@installed_at_exit", true)
181
+ rescue LoadError
182
+ # noop
183
+ end
184
+
185
+ if ENV['RAILS_TEST_HELPER']
186
+ require ENV['RAILS_TEST_HELPER']
187
+ else
188
+ if File.exists?(ROOT_PATH + "/spec/spec_helper.rb")
189
+ require 'spec_helper'
190
+ elsif File.exists?(ROOT_PATH + "/test/minitest_helper.rb")
191
+ require 'minitest_helper'
192
+ else
193
+ require 'test_helper'
194
+ end
195
+ end
196
+ end
197
+
198
+ def test(argv=ARGV)
199
+ if spec_file?(argv) && defined?(RSpec)
200
+ # disable autorun in case the user left it in spec_helper.rb
201
+ RSpec::Core::Runner.disable_autorun!
202
+ exit RSpec::Core::Runner.run(argv)
203
+ else
204
+ Zeus::M.run(argv)
205
+ end
206
+ end
207
+
208
+ private
209
+
210
+ SPEC_DIR_REGEXP = %r"(^|/)spec"
211
+ SPEC_FILE_REGEXP = /.+_spec\.rb$/
212
+
213
+ def spec_file? argv
214
+ argv.any? do |arg|
215
+ arg.match(Regexp.union(SPEC_DIR_REGEXP, SPEC_FILE_REGEXP))
216
+ end
217
+ end
218
+
219
+ def restart_girl_friday
220
+ return unless defined?(GirlFriday::WorkQueue)
221
+ # The Actor is run in a thread, and threads don't persist post-fork.
222
+ # We just need to restart each one in the newly-forked process.
223
+ ObjectSpace.each_object(GirlFriday::WorkQueue) do |obj|
224
+ obj.send(:start)
225
+ end
226
+ end
227
+
228
+ def reconnect_activerecord
229
+ return unless defined?(ActiveRecord::Base)
230
+ begin
231
+ ActiveRecord::Base.clear_all_connections!
232
+ ActiveRecord::Base.establish_connection
233
+ if ActiveRecord::Base.respond_to?(:shared_connection)
234
+ ActiveRecord::Base.shared_connection = ActiveRecord::Base.retrieve_connection
235
+ end
236
+ rescue ActiveRecord::AdapterNotSpecified
237
+ end
238
+ end
239
+
240
+ def reconnect_redis
241
+ return unless defined?(Redis::Client)
242
+ ObjectSpace.each_object(Redis::Client) do |client|
243
+ client.connect rescue nil
244
+ end
245
+ end
246
+
247
+ def load_rails_generators
248
+ require 'rails/generators'
249
+ ::Rails.application.load_generators
250
+ rescue LoadError # Rails 3.0 doesn't require this block to be run, but 3.2+ does
251
+ end
252
+
253
+ end
254
+ end
255
+
256
+ Zeus.plan ||= Zeus::Rails.new
@@ -0,0 +1,3 @@
1
+ module Zeus
2
+ VERSION = '0.13.5'
3
+ end
@@ -0,0 +1,42 @@
1
+ module MiniTest
2
+ module Unit
3
+ class TestCase
4
+ end
5
+ end
6
+ end
7
+
8
+ def stub_mini_test_methods
9
+ MiniTest::Unit::TestCase.stub!(:test_suites).and_return [fake_suite]
10
+ MiniTest::Unit.stub!(:runner).and_return fake_runner
11
+ end
12
+
13
+ def fake_runner
14
+ @runner ||= stub("Runner", :run => 0)
15
+ end
16
+
17
+ def fake_suite
18
+ @suite ||= stub("TestSuite",
19
+ :test_methods => [fake_test_method],
20
+ :instance_method => fake_instance_method)
21
+ end
22
+
23
+ def fake_suite_with_special_characters
24
+ @suite ||= stub("TestSuite",
25
+ :test_methods => [fake_special_characters_test_method],
26
+ :instance_method => fake_instance_method(fake_special_characters_test_method))
27
+ end
28
+
29
+ def fake_test_method
30
+ "test_method"
31
+ end
32
+
33
+ def fake_special_characters_test_method
34
+ "test_my_test_method?"
35
+ end
36
+
37
+ def fake_instance_method(name=fake_test_method)
38
+ @instance_method ||= stub("InstanceMethod",
39
+ :source_location => ["path/to/file.rb", 2],
40
+ :source => "def #{name} \n assert true \n end")
41
+ end
42
+
data/spec/m_spec.rb ADDED
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'fake_mini_test'
3
+
4
+ module Zeus::M
5
+ describe Runner do
6
+
7
+ context "given a test with a question mark" do
8
+ before do
9
+ MiniTest::Unit::TestCase.stub!(:test_suites).and_return [fake_suite_with_special_characters]
10
+ MiniTest::Unit.stub!(:runner).and_return fake_runner
11
+ end
12
+
13
+ it "escapes the question mark when using line number" do
14
+ argv = ["path/to/file.rb:2"]
15
+
16
+ fake_runner.should_receive(:run).with(["-n", "/(test_my_test_method\\?)/"])
17
+
18
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
19
+ end
20
+
21
+ it "escapes the question mark from explicit names" do
22
+ argv = ["path/to/file.rb", "--name", fake_special_characters_test_method]
23
+
24
+ fake_runner.should_receive(:run).with(["-n", "test_my_test_method\\?"])
25
+
26
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe Runner do
32
+ before do
33
+ stub_mini_test_methods
34
+ end
35
+
36
+ context "no option is given" do
37
+ it "runs the test without giving any option" do
38
+ argv = ["path/to/file.rb"]
39
+
40
+ fake_runner.should_receive(:run).with([])
41
+
42
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
43
+ end
44
+ end
45
+
46
+ context "given a line number" do
47
+ it "aborts if no test is found" do
48
+ argv = ["path/to/file.rb:100"]
49
+
50
+ STDERR.should_receive(:write).with(/No tests found on line 100/)
51
+ fake_runner.should_not_receive :run
52
+
53
+ lambda { Runner.new(argv).run }.should_not exit_with_code(0)
54
+ end
55
+
56
+ it "runs the test if the correct line number is given" do
57
+ argv = ["path/to/file.rb:2"]
58
+
59
+ fake_runner.should_receive(:run).with(["-n", "/(#{fake_test_method})/"])
60
+
61
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
62
+ end
63
+ end
64
+
65
+ context "specifying test name" do
66
+ it "runs the specified tests when using a pattern in --name option" do
67
+ argv = ["path/to/file.rb", "--name", "/#{fake_test_method}/"]
68
+
69
+ fake_runner.should_receive(:run).with(["-n", "/#{fake_test_method}/"])
70
+
71
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
72
+ end
73
+
74
+ it "runs the specified tests when using a pattern in -n option" do
75
+ argv = ["path/to/file.rb", "-n", "/method/"]
76
+
77
+ fake_runner.should_receive(:run).with(["-n", "/method/"])
78
+
79
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
80
+ end
81
+
82
+ it "aborts if no test matches the given pattern" do
83
+ argv = ["path/to/file.rb", "-n", "/garbage/"]
84
+
85
+ STDERR.should_receive(:write).with(%r{No test name matches \'/garbage/\'})
86
+ fake_runner.should_not_receive :run
87
+
88
+ lambda { Runner.new(argv).run }.should_not exit_with_code(0)
89
+ end
90
+
91
+ it "runs the specified tests when using a name (no pattern)" do
92
+ argv = ["path/to/file.rb", "-n", "#{fake_test_method}"]
93
+
94
+ fake_runner.should_receive(:run).with(["-n", fake_test_method])
95
+
96
+ lambda { Runner.new(argv).run }.should exit_with_code(0)
97
+ end
98
+
99
+ it "aborts if no test matches the given test name" do
100
+ argv = ["path/to/file.rb", "-n", "method"]
101
+
102
+ STDERR.should_receive(:write).with(%r{No test name matches \'method\'})
103
+ fake_runner.should_not_receive :run
104
+
105
+ lambda { Runner.new(argv).run }.should_not exit_with_code(0)
106
+ end
107
+ end
108
+ end
109
+
110
+ end