spec/runner_spec.rb in mislav-rspactor-0.3.2 vs spec/runner_spec.rb in mislav-rspactor-0.3.3
- old
+ new
@@ -1,105 +1,159 @@
require 'rspactor/runner'
describe RSpactor::Runner do
described_class.class_eval do
- def self.run_command(cmd)
+ def run_command(cmd)
# never shell out in tests
cmd
end
end
- def runner
- described_class
- end
-
def with_env(name, value)
old_value = ENV[name]
ENV[name] = value
begin
yield
ensure
ENV[name] = old_value
end
end
- describe "setup" do
+ def capture_stderr(io = StringIO.new)
+ @old_stderr, $stderr = $stderr, io
+ begin; yield ensure; restore_stderr; end if block_given?
+ end
+
+ def restore_stderr
+ $stderr = @old_stderr
+ end
+
+ def capture_stdout(io = StringIO.new)
+ @old_stdout, $stdout = $stdout, io
+ begin; yield ensure; restore_stdout; end if block_given?
+ end
+
+ def restore_stdout
+ $stdout = @old_stdout
+ end
+
+ describe "start" do
before(:each) do
- Dir.stub!(:pwd).and_return('/my/path')
- File.stub!(:exists?).and_return(false)
- runner.stub!(:puts)
- RSpactor::Inspector.stub!(:new)
- RSpactor::Interactor.stub!(:new).and_return(mock('Interactor').as_null_object)
- RSpactor::Listener.stub!(:new).and_return(mock('Listener').as_null_object)
+ @runner = described_class.new('/my/path')
+ capture_stdout
end
- def setup
- runner.load
+ after(:each) do
+ restore_stdout
end
- it "should initialize Inspector" do
- RSpactor::Inspector.should_receive(:new).with('/my/path')
- setup
+ def setup
+ @runner.start
end
+
+ context "Interactor" do
+ before(:each) do
+ @runner.stub!(:load_dotfile)
+ @runner.stub!(:start_listener)
+ @interactor = mock('Interactor')
+ @interactor.should_receive(:start_termination_handler)
+ RSpactor::Interactor.should_receive(:new).and_return(@interactor)
+ end
+
+ it "should start Interactor" do
+ @interactor.should_receive(:wait_for_enter_key).with(instance_of(String), 3)
+ setup
+ end
- it "should start Interactor" do
- interactor = mock('Interactor')
- interactor.should_receive(:wait_for_enter_key).with(instance_of(String), 3)
- interactor.should_receive(:start_termination_handler)
- RSpactor::Interactor.should_receive(:new).and_return(interactor)
- setup
- end
+ it "should run all specs if Interactor isn't interrupted" do
+ @interactor.should_receive(:wait_for_enter_key).and_return(nil)
+ @runner.should_receive(:run_spec_command).with('spec')
+ setup
+ end
- it "should run all specs if Interactor isn't interrupted" do
- interactor = mock('Interactor', :start_termination_handler => nil)
- interactor.should_receive(:wait_for_enter_key).and_return(nil)
- RSpactor::Interactor.should_receive(:new).and_return(interactor)
- runner.should_receive(:run_spec_command).with('spec')
- setup
+ it "should skip running all specs if Interactor is interrupted" do
+ @interactor.should_receive(:wait_for_enter_key).and_return(true)
+ @runner.should_not_receive(:run_spec_command)
+ setup
+ end
end
-
- it "should skip running all specs if Interactor is interrupted" do
- interactor = mock('Interactor', :start_termination_handler => nil)
- interactor.should_receive(:wait_for_enter_key).and_return(true)
- RSpactor::Interactor.should_receive(:new).and_return(interactor)
- runner.should_not_receive(:run_spec_command)
+
+ it "should initialize Inspector" do
+ @runner.stub!(:load_dotfile)
+ @runner.stub!(:start_interactor)
+ RSpactor::Inspector.should_receive(:new).with('/my/path')
+ RSpactor::Listener.stub!(:new).and_return(mock('Listener').as_null_object)
setup
end
-
- it "should run Listener" do
- listener = mock('Listener')
- listener.should_receive(:run).with('/my/path')
- RSpactor::Listener.should_receive(:new).with(instance_of(Array)).and_return(listener)
- setup
+
+ context "Listener" do
+ before(:each) do
+ @runner.stub!(:load_dotfile)
+ @runner.stub!(:start_interactor)
+ @inspector = mock("Inspector")
+ RSpactor::Inspector.stub!(:new).and_return(@inspector)
+ @listener = mock('Listener')
+ end
+
+ it "should run Listener" do
+ @listener.should_receive(:run).with('/my/path')
+ RSpactor::Listener.should_receive(:new).with(instance_of(Array)).and_return(@listener)
+ setup
+ end
end
it "should output 'watching' message on start" do
- runner.should_receive(:puts).with("** RSpactor is now watching at '/my/path'")
+ @runner.stub!(:load_dotfile)
+ @runner.stub!(:start_interactor)
+ @runner.stub!(:start_listener)
setup
+ $stdout.string.chomp.should == "** RSpactor is now watching at '/my/path'"
end
- it "should load dotfile if found" do
- with_env('HOME', '/home/moo') do
- File.should_receive(:exists?).with('/home/moo/.rspactor').and_return(true)
- Kernel.should_receive(:load).with('/home/moo/.rspactor')
- setup
+ context "dotfile" do
+ before(:each) do
+ @runner.stub!(:start_interactor)
+ @runner.stub!(:start_listener)
end
+
+ it "should load dotfile if found" do
+ with_env('HOME', '/home/moo') do
+ File.should_receive(:exists?).with('/home/moo/.rspactor').and_return(true)
+ Kernel.should_receive(:load).with('/home/moo/.rspactor')
+ setup
+ end
+ end
+
+ it "should continue even if the dotfile raised errors" do
+ with_env('HOME', '/home/moo') do
+ File.should_receive(:exists?).and_return(true)
+ Kernel.should_receive(:load).with('/home/moo/.rspactor').and_raise(ArgumentError)
+ capture_stderr do
+ lambda { setup }.should_not raise_error
+ $stderr.string.split("\n").should include('Error while loading /home/moo/.rspactor: ArgumentError')
+ end
+ end
+ end
end
end
describe "#run_spec_command" do
+ before(:each) do
+ @runner = described_class.new('/my/path')
+ end
+
def with_rubyopt(string, &block)
with_env('RUBYOPT', string, &block)
end
def run(paths)
- runner.run_spec_command(paths)
+ @runner.run_spec_command(paths)
end
it "should exit if the paths argument is empty" do
- runner.should_not_receive(:run_command)
+ @runner.should_not_receive(:run_command)
run([])
end
it "should specify runner spec runner with joined paths" do
run(%w(foo bar)).should include(' spec foo bar ')
@@ -128,16 +182,63 @@
it "should include 'progress' formatter" do
run('foo').should include(' -f progress')
end
it "should not include 'progress' formatter if there already are 2 or more formatters" do
- runner.should_receive(:formatter_opts).and_return('-f foo --format bar')
+ @runner.should_receive(:formatter_opts).and_return('-f foo --format bar')
run('foo').should_not include('-f progress')
end
+
+ it "should save status of last run" do
+ @runner.should_receive(:run_command).twice.and_return(true, false)
+ run('foo')
+ @runner.last_run_failed?.should be_false
+ run('bar')
+ @runner.last_run_failed?.should be_true
+ run([])
+ @runner.last_run_failed?.should be_false
+ end
end
+ describe "#spec_changed_files" do
+ before(:each) do
+ @runner = described_class.new('.')
+ @runner.stub!(:inspector).and_return(mock("Inspector"))
+ end
+
+ def set_inspector_expectation(file, ret)
+ @runner.inspector.should_receive(:determine_spec_files).with(file).and_return(ret)
+ end
+
+ it "should find and run spec files" do
+ set_inspector_expectation('moo.rb', ['spec/moo_spec.rb'])
+ set_inspector_expectation('views/baz.haml', [])
+ set_inspector_expectation('config/bar.yml', ['spec/bar_spec.rb', 'spec/bar_stuff_spec.rb'])
+
+ expected = %w(spec/moo_spec.rb spec/bar_spec.rb spec/bar_stuff_spec.rb)
+ @runner.should_receive(:run_spec_command).with(expected)
+
+ capture_stdout do
+ @runner.send(:spec_changed_files, %w(moo.rb views/baz.haml config/bar.yml))
+ $stdout.string.split("\n").should == expected
+ end
+ end
+
+ it "should run the full suite after a run succeded when the previous one failed" do
+ @runner.inspector.stub!(:determine_spec_files).and_return(['spec/foo_spec.rb'], ['spec/bar_spec.rb'])
+ @runner.stub!(:options).and_return({ :retry_failed => true })
+
+ capture_stdout do
+ @runner.stub!(:run_spec_command)
+ @runner.should_receive(:last_run_failed?).and_return(true, false)
+ @runner.should_receive(:run_all_specs)
+ @runner.send(:spec_changed_files, %w(moo.rb))
+ end
+ end
+ end
+
it "should have Runner in global namespace for backwards compatibility" do
defined?(::Runner).should be_true
- ::Runner.should == runner
+ ::Runner.should == described_class
end
end
\ No newline at end of file