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