diff --git a/lib/hydra/message/runner_messages.rb b/lib/hydra/message/runner_messages.rb index 1f42885..4010ed1 100644 --- a/lib/hydra/message/runner_messages.rb +++ b/lib/hydra/message/runner_messages.rb @@ -29,6 +29,15 @@ module Hydra #:nodoc: # the connectivity of the IO end end + + # The runner forks to run rspec messages + # so that specs don't get rerun. It uses + # this message to report the results. See + # Runner::run_rspec_file. + class RSpecResult < Hydra::Message + # the output of the spec + attr_accessor :output + end end end end diff --git a/lib/hydra/runner.rb b/lib/hydra/runner.rb index 2956443..187cf66 100644 --- a/lib/hydra/runner.rb +++ b/lib/hydra/runner.rb @@ -35,10 +35,12 @@ module Hydra #:nodoc: trace "Running file: #{file}" output = "" - if file =~ /.rb$/ - output = run_ruby_file(file) + if file =~ /_spec.rb$/ + output = run_rspec_file(file) elsif file =~ /.feature$/ output = run_cucumber_file(file) + else + output = run_test_unit_file(file) end output = "." if output == "" @@ -75,15 +77,6 @@ module Hydra #:nodoc: end end - # Run a ruby file (ending in .rb) - def run_ruby_file(file) - if file =~ /_spec.rb$/ - return run_rspec_file(file) - else - return run_test_unit_file(file) - end - end - # Run all the Test::Unit Suites in a ruby file def run_test_unit_file(file) begin @@ -110,31 +103,35 @@ module Hydra #:nodoc: # run all the Specs in an RSpec file (NOT IMPLEMENTED) def run_rspec_file(file) - # TODO: - # 1. do some of this only once, like the requires and stuff - # 2. fork the file loading so that it doesn't get re-run - # 3. test that running two files doesn't re-run the first - # to test 2. above. Like for cucumber - # 4. try this on a real rspec project + # pull in rspec begin require 'spec/autorun' + require 'hydra/spec/hydra_formatter' rescue LoadError => ex return ex.to_s end - options = Spec::Runner.options - require 'spec/runner/formatter/progress_bar_formatter' - require 'hydra/spec/hydra_formatter' - hydra_output = StringIO.new - options.formatters = [Spec::Runner::Formatter::HydraFormatter.new(options.formatter_options, hydra_output)] - require file - options.run_examples - hydra_output.rewind - output = hydra_output.read.chomp - output = "" if output == "." - + # we have to run the rspec test in a sub-process + # this is because rspec runs all the tests that + # have been required, so if we kept requiring the + # files they'd get run over and over + pipe = Hydra::Pipe.new + pid = SafeFork.fork do + pipe.identify_as_child + options = Spec::Runner.options + hydra_output = StringIO.new + options.formatters = [Spec::Runner::Formatter::HydraFormatter.new(options.formatter_options, hydra_output)] + require file + options.run_examples + hydra_output.rewind + output = hydra_output.read.chomp + output = "" if output == "." + pipe.write RSpecResult.new(:output => output) + pipe.close + end + pipe.identify_as_parent + output = pipe.gets + Process.wait pid return output - - #return `spec #{File.expand_path(file)}` end # run all the scenarios in a cucumber feature file diff --git a/lib/hydra/spec/hydra_formatter.rb b/lib/hydra/spec/hydra_formatter.rb index 9ea5cff..a19a2e4 100644 --- a/lib/hydra/spec/hydra_formatter.rb +++ b/lib/hydra/spec/hydra_formatter.rb @@ -1,3 +1,5 @@ +require 'spec/autorun' +require 'spec/runner/formatter/progress_bar_formatter' module Spec module Runner class Options diff --git a/test/fixtures/write_file_alternate_spec.rb b/test/fixtures/write_file_alternate_spec.rb new file mode 100644 index 0000000..f0e611a --- /dev/null +++ b/test/fixtures/write_file_alternate_spec.rb @@ -0,0 +1,9 @@ +require 'tmpdir' +context "file writing" do + it "writes to a file" do + File.open(File.join(Dir.tmpdir, 'alternate_hydra_test.txt'), 'a') do |f| + f.write "HYDRA" + end + end +end + diff --git a/test/runner_test.rb b/test/runner_test.rb index f5dc9a5..c293a87 100644 --- a/test/runner_test.rb +++ b/test/runner_test.rb @@ -37,29 +37,43 @@ class RunnerTest < Test::Unit::TestCase Process.wait(child) end - should "run two cucumber tests" do - puts "THE FOLLOWING WARNINGS CAN BE IGNORED" - puts "It is caused by Cucumber loading all rb files near its features" - - runner = Hydra::Runner.new(:io => File.new('/dev/null', 'w')) - runner.run_file(cucumber_feature_file) - assert File.exists?(target_file) - assert_equal "HYDRA", File.read(target_file) - - FileUtils.rm_f(target_file) - - runner.run_file(alternate_cucumber_feature_file) - assert File.exists?(alternate_target_file) - assert_equal "HYDRA", File.read(alternate_target_file) - - puts "END IGNORABLE OUTPUT" - end - - should "run an rspec test" do + should "run two rspec tests" do runner = Hydra::Runner.new(:io => File.new('/dev/null', 'w')) runner.run_file(rspec_file) assert File.exists?(target_file) assert_equal "HYDRA", File.read(target_file) + + FileUtils.rm_f(target_file) + + runner.run_file(alternate_rspec_file) + assert File.exists?(alternate_target_file) + assert_equal "HYDRA", File.read(alternate_target_file) + assert !File.exists?(target_file) + end + + should "run two cucumber tests" do + # because of all the crap cucumber pulls in + # we run this in a fork to not contaminate + # the main test environment + pid = Process.fork do + puts "THE FOLLOWING WARNINGS CAN BE IGNORED" + puts "It is caused by Cucumber loading all rb files near its features" + + runner = Hydra::Runner.new(:io => File.new('/dev/null', 'w')) + runner.run_file(cucumber_feature_file) + assert File.exists?(target_file) + assert_equal "HYDRA", File.read(target_file) + + FileUtils.rm_f(target_file) + + runner.run_file(alternate_cucumber_feature_file) + assert File.exists?(alternate_target_file) + assert_equal "HYDRA", File.read(alternate_target_file) + assert !File.exists?(target_file) + + puts "END IGNORABLE OUTPUT" + end + Process.wait pid end should "be able to run a runner over ssh" do diff --git a/test/test_helper.rb b/test/test_helper.rb index dd2dcf2..b989da1 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -27,6 +27,10 @@ class Test::Unit::TestCase File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'write_file_spec.rb')) end + def alternate_rspec_file + File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'write_file_alternate_spec.rb')) + end + def cucumber_feature_file File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'features', 'write_file.feature')) end