From 4fa3b4e506b3f2c1101f3b1277af55c9af7c165c Mon Sep 17 00:00:00 2001 From: Agis Anastasopoulos Date: Sun, 20 Sep 2020 23:50:07 +0300 Subject: [PATCH] Split spec files to examples programmatically Instead of shelling out to rspec, we now split spec files into individual examples programmatically, using the RSpec Core API. This is faster and more robust, since we avoid common shell shenanigans. Closes #6 --- lib/rspecq/worker.rb | 37 ++++++++++++++----------------------- test/test_scheduling.rb | 2 +- test/test_worker.rb | 4 ++-- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/rspecq/worker.rb b/lib/rspecq/worker.rb index a999698..10e7437 100644 --- a/lib/rspecq/worker.rb +++ b/lib/rspecq/worker.rb @@ -168,33 +168,24 @@ def try_publish_queue!(queue) # falling back to scheduling them as whole files. Their errors will be # reported in the normal flow when they're eventually picked up by a worker. def files_to_example_ids(files) - cmd = "DISABLE_SPRING=1 bundle exec rspec --dry-run --format json #{files.join(' ')} 2>&1" - out = `#{cmd}` - cmd_result = $? + out = StringIO.new - if !cmd_result.success? - rspec_output = begin - JSON.parse(out) - rescue JSON::ParserError - out - end + reset_rspec_state! - log_event( - "Failed to split slow files, falling back to regular scheduling", - "error", - rspec_output: rspec_output, - cmd_result: cmd_result.inspect, - ) - - pp rspec_output - - return files - end - - JSON.parse(out)["examples"].map { |e| e["id"] } + RSpec.configuration.add_formatter(RSpec::Core::Formatters::JsonFormatter.new(out)) + RSpec.configuration.files_or_directories_to_run = files_or_dirs_to_run + RSpec.configuration.dry_run = true + + opts = RSpec::Core::ConfigurationOptions.new(files) + result = RSpec::Core::Runner.new(opts).run($stderr, $stdout) + return files if result != 0 + JSON.parse(out.string)["examples"].map { |e| e["id"] } + ensure + RSpec.configuration.dry_run = false + # clear formatters + reset_rspec_state! end - private def reset_rspec_state! diff --git a/test/test_scheduling.rb b/test/test_scheduling.rb index 0a2f0ed..1b33609 100644 --- a/test/test_scheduling.rb +++ b/test/test_scheduling.rb @@ -47,7 +47,7 @@ def test_scheduling_with_timings_and_splitting worker = new_worker("scheduling") worker.populate_timings = true worker.file_split_threshold = 0.2 - silent { worker.try_publish_queue!(worker.queue) } + worker.try_publish_queue!(worker.queue) assert_equal [ "./test/sample_suites/scheduling/spec/foo_spec.rb[1:2:1]", diff --git a/test/test_worker.rb b/test/test_worker.rb index 146fc82..b9884b8 100644 --- a/test/test_worker.rb +++ b/test/test_worker.rb @@ -18,7 +18,7 @@ def test_files_to_example_ids ] ) - assert_equal expected, actual + assert_equal expected.sort, actual.sort end def test_files_to_example_ids_failure_fallback @@ -36,6 +36,6 @@ def test_files_to_example_ids_failure_fallback ] ) - assert_equal expected, actual + assert_equal expected.sort, actual.sort end end