diff --git a/README.md b/README.md index f74c1f54..8b022a47 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ notification: false # Display notification after the specs are done running, run_all: { cmd: 'custom rspec command', message: 'custom message' } # Custom options to use when running all specs title: 'My project' # Display a custom title for the notification, default: 'RSpec results' chdir: 'directory' # run rspec from within a given subdirectory (useful if project has separate specs for submodules) +results_file: 'some/path' # use the given file for storing results (instead of default relative path) ``` ### Using Launchy to view rspec results diff --git a/lib/guard/rspec/rspec_process.rb b/lib/guard/rspec/rspec_process.rb index 2c1900ca..09054f84 100644 --- a/lib/guard/rspec/rspec_process.rb +++ b/lib/guard/rspec/rspec_process.rb @@ -34,7 +34,8 @@ def _run end def _really_run - pid = Kernel.spawn(command) # use spawn to stub in JRuby + env = { "GUARD_RSPEC_RESULTS_FILE" => formatter_tmp_file } + pid = Kernel.spawn(env, command) # use spawn to stub in JRuby result = Process.wait2(pid) result.last.exitstatus rescue Errno::ENOENT => ex diff --git a/lib/guard/rspec/runner.rb b/lib/guard/rspec/runner.rb index 1b6aac56..eb2590b5 100644 --- a/lib/guard/rspec/runner.rb +++ b/lib/guard/rspec/runner.rb @@ -49,7 +49,8 @@ def reload def _run(paths, options, &block) fail NoCmdOptionError unless options[:cmd] - _really_run(paths, options, &block) + command = Command.new(paths, options) + _really_run(command, options, &block) true rescue RSpecProcess::Failure, NoCmdOptionError => ex Compat::UI.error(ex.to_s) @@ -57,11 +58,11 @@ def _run(paths, options, &block) false end - def _really_run(paths, options) + def _really_run(cmd, options) # TODO: add option to specify the file - file = _tmp_file(options[:chdir]) + file = _results_file(options[:results_file], options[:chdir]) - process = RSpecProcess.new(Command.new(paths, options), file) + process = RSpecProcess.new(cmd, file) results = process.results inspector.failed(results.failed_paths) @@ -78,8 +79,10 @@ def _open_launchy ::Launchy.open(options[:launchy]) if pn.exist? end - def _tmp_file(chdir) - chdir ? File.join(chdir, TEMPORARY_FILE_PATH) : TEMPORARY_FILE_PATH + def _results_file(results_file, chdir) + results_file ||= TEMPORARY_FILE_PATH + return results_file unless Pathname(results_file).relative? + chdir ? File.join(chdir, results_file) : results_file end end end diff --git a/lib/guard/rspec_formatter.rb b/lib/guard/rspec_formatter.rb index bd7dc457..e31af3b6 100644 --- a/lib/guard/rspec_formatter.rb +++ b/lib/guard/rspec_formatter.rb @@ -9,8 +9,6 @@ module Guard class RSpecFormatter < ::RSpec::Core::Formatters::BaseFormatter - TEMPORARY_FILE_PATH ||= "tmp/rspec_guard_result" - def self.rspec_3? ::RSpec::Core::Version::STRING.split(".").first == "3" end @@ -82,7 +80,7 @@ def write_summary(duration, total, failures, pending) end def _write(&block) - file = File.expand_path(TEMPORARY_FILE_PATH) + file = _results_file FileUtils.mkdir_p(File.dirname(file)) File.open(file, "w", &block) end @@ -109,5 +107,11 @@ def _status_failed?(example) example.execution_result[:status].to_s == "failed" end end + + def _results_file + path = ENV["GUARD_RSPEC_RESULTS_FILE"] + fail "Fatal: No output file given for Guard::RSpec formatter!" unless path + File.expand_path(path) + end end end diff --git a/spec/lib/guard/rspec/command_spec.rb b/spec/lib/guard/rspec/command_spec.rb index b8d2452f..30285e90 100644 --- a/spec/lib/guard/rspec/command_spec.rb +++ b/spec/lib/guard/rspec/command_spec.rb @@ -46,6 +46,13 @@ end context "with no RSpec defined formatter" do + before do + allow(RSpec::Core::ConfigurationOptions).to receive(:new) do + instance_double(RSpec::Core::ConfigurationOptions, + options: { formatters: nil }) + end + end + it "sets default progress formatter" do expect(command).to match %r{-f progress} end diff --git a/spec/lib/guard/rspec/rspec_process_spec.rb b/spec/lib/guard/rspec/rspec_process_spec.rb index 48d6a410..9d75be9e 100644 --- a/spec/lib/guard/rspec/rspec_process_spec.rb +++ b/spec/lib/guard/rspec/rspec_process_spec.rb @@ -23,8 +23,11 @@ end before do + allow(Kernel).to receive(:spawn). + with({ "GUARD_RSPEC_RESULTS_FILE" => file }, cmd).and_return(pid) + allow(Guard::RSpec::Results).to receive(:new). - with("foobar.txt").and_return(results) + with(file).and_return(results) end context "with an non-existing command" do @@ -41,7 +44,6 @@ context "with an existing command" do before do - allow(Kernel).to receive(:spawn).with(cmd).and_return(pid) allow(Process).to receive(:wait2).with(pid).and_return(wait_result) end @@ -65,8 +67,7 @@ end context "with no failures" do - it "spawns and waits" do - expect(Kernel).to receive(:spawn).with(cmd).and_return(pid) + it "waits for process to end" do expect(Process).to receive(:wait2).with(pid).and_return(wait_result) subject end diff --git a/spec/lib/guard/rspec/runner_spec.rb b/spec/lib/guard/rspec/runner_spec.rb index ff93e718..633ff046 100644 --- a/spec/lib/guard/rspec/runner_spec.rb +++ b/spec/lib/guard/rspec/runner_spec.rb @@ -191,6 +191,66 @@ end end + context "with a custom results file" do + let(:options) do + { cmd: "rspec", results_file: results_file }.merge(chdir_options) + end + + context "with no chdir option" do + let(:chdir_options) { {} } + + context "when the path is relative" do + let(:results_file) { "foobar.txt" } + it "uses the given file" do + expect(Guard::RSpec::RSpecProcess).to receive(:new). + with(anything, results_file).and_return(process) + runner.run(paths) + end + end + + context "when the path is absolute" do + let(:results_file) { "/foo/foobar.txt" } + it "uses the given path" do + expect(Guard::RSpec::RSpecProcess).to receive(:new). + with(anything, results_file).and_return(process) + runner.run(paths) + end + end + end + + context "with chdir option" do + let(:chdir_options) { { chdir: "moduleA" } } + + context "when the path is relative" do + let(:results_file) { "foobar.txt" } + + it "uses a path relative to chdir" do + expect(Guard::RSpec::RSpecProcess).to receive(:new). + with(anything, "moduleA/foobar.txt").and_return(process) + runner.run(paths) + end + end + + context "when the path is absolute" do + let(:results_file) { "/foo/foobar.txt" } + it "uses the full given path anyway" do + expect(Guard::RSpec::RSpecProcess).to receive(:new). + with(anything, results_file).and_return(process) + runner.run(paths) + end + end + end + end + + context "with no custom results file" do + let(:options) { { cmd: "rspec" } } + it "uses the default" do + expect(Guard::RSpec::RSpecProcess).to receive(:new). + with(anything, "tmp/rspec_guard_result").and_return(process) + runner.run(paths) + end + end + it "notifies inspector about failed paths" do expect(inspector).to receive(:failed).with([]) runner.run(paths) @@ -225,19 +285,4 @@ runner.run(paths) end end - - # TODO: remove / cleanup - describe "_tmp_file" do - subject { described_class.new.send(:_tmp_file, chdir) } - - context "with no chdir option" do - let(:chdir) { nil } - it { is_expected.to eq("tmp/rspec_guard_result") } - end - - context "chdir option" do - let(:chdir) { "moduleA" } - it { is_expected.to eq("moduleA/tmp/rspec_guard_result") } - end - end end diff --git a/spec/lib/guard/rspec_formatter_spec.rb b/spec/lib/guard/rspec_formatter_spec.rb index 4b3e9aab..103eaa04 100644 --- a/spec/lib/guard/rspec_formatter_spec.rb +++ b/spec/lib/guard/rspec_formatter_spec.rb @@ -1,11 +1,6 @@ require "guard/rspec_formatter" RSpec.describe Guard::RSpecFormatter do - describe "::TEMPORARY_FILE_PATH" do - subject { Pathname.new(described_class::TEMPORARY_FILE_PATH) } - it { is_expected.to be_relative } - end - describe "#dump_summary" do def rspec_summary_args(*args) return args unless ::RSpec::Core::Version::STRING.start_with?("3.") @@ -53,8 +48,15 @@ def rspec_summary_args(*args) context "without stubbed IO" do let(:stub_formatter) { false } + around do |example| + env_var = "GUARD_RSPEC_RESULTS_FILE" + old, ENV[env_var] = ENV[env_var], "foobar.txt" + example.run + ENV[env_var] = old + end + it "creates temporary file and and writes to it" do - file = File.expand_path(described_class::TEMPORARY_FILE_PATH) + file = File.expand_path("foobar.txt") expect(FileUtils).to receive(:mkdir_p). with(File.dirname(file)) {}