diff --git a/README.md b/README.md index f5a285a..a82b1e7 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,18 @@ Options: --seed SEED Seed for rspec ``` +To pass any options supported by paralell_tests, use `--`: + +```bash +bundle exec turbo_tests -n 4 -- --only-group 1 --pattern spec/system +``` + +`turbo_tests` supports custom formatter such as Fuubar, but you might need to require it: + +```bash +bundle exec turbo_tests -r fuubar -f Fuubar spec/whatever +``` + ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. diff --git a/lib/turbo_tests/cli.rb b/lib/turbo_tests/cli.rb index 6f033cc..d914060 100644 --- a/lib/turbo_tests/cli.rb +++ b/lib/turbo_tests/cli.rb @@ -98,15 +98,19 @@ def run end end + parallel_options = ParallelTests::CLI.new.send(:parse_options!, @argv.unshift("--type", "rspec")) + files = parallel_options.fetch(:files, ["spec"]) + exitstatus = TurboTests::Runner.run( formatters: formatters, tags: tags, - files: @argv.empty? ? ["spec"] : @argv, + files: files, runtime_log: runtime_log, verbose: verbose, fail_fast: fail_fast, count: count, - seed: seed + seed: seed, + parallel_options: parallel_options ) # From https://github.com/serpapi/turbo_tests/pull/20/ diff --git a/lib/turbo_tests/reporter.rb b/lib/turbo_tests/reporter.rb index 417f06a..364dae6 100644 --- a/lib/turbo_tests/reporter.rb +++ b/lib/turbo_tests/reporter.rb @@ -4,8 +4,8 @@ module TurboTests class Reporter attr_writer :load_time - def self.from_config(formatter_config, start_time, seed, seed_used) - reporter = new(start_time, seed, seed_used) + def self.from_config(formatter_config, *args) + reporter = new(*args) formatter_config.each do |config| name, outputs = config.values_at(:name, :outputs) @@ -23,7 +23,7 @@ def self.from_config(formatter_config, start_time, seed, seed_used) attr_reader :pending_examples attr_reader :failed_examples - def initialize(start_time, seed, seed_used) + def initialize(start_time, seed, seed_used, files, parallel_options) @formatters = [] @pending_examples = [] @failed_examples = [] @@ -34,6 +34,9 @@ def initialize(start_time, seed, seed_used) @seed_used = seed_used @load_time = 0 @errors_outside_of_examples_count = 0 + @files = files + @parallel_options = parallel_options + @custom_formatters = false end def add(name, outputs) @@ -45,6 +48,7 @@ def add(name, outputs) when "d", "documentation" RSpec::Core::Formatters::DocumentationFormatter else + @custom_formatters = true Kernel.const_get(name) end @@ -70,8 +74,10 @@ def start(example_groups, time=RSpec::Core::Time.now) report_number_of_tests(example_groups) expected_example_count = example_groups.flatten(1).count + examples_count = self.examples_count if @custom_formatters + delegate_to_formatters(:seed, RSpec::Core::Notifications::SeedNotification.new(@seed, @seed_used)) - delegate_to_formatters(:start, RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time)) + delegate_to_formatters(:start, RSpec::Core::Notifications::StartNotification.new(examples_count, @load_time)) end def report_number_of_tests(groups) @@ -84,6 +90,15 @@ def report_number_of_tests(groups) puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process" end + def examples_count + files = ParallelTests::RSpec::Runner.send(:find_tests, @files, @parallel_options) + output_file = Tempfile.new("rspec-summary") + `#{ENV.fetch("BUNDLE_BIN_PATH")} exec rspec --dry-run --format json --out='#{output_file.path}' #{files.join(" ")}` + + json_summary = JSON.parse(output_file.read, symbolize_names: true) + json_summary.dig(:summary, :example_count) || 0 + end + def group_started(notification) delegate_to_formatters(:example_group_started, notification) end diff --git a/lib/turbo_tests/runner.rb b/lib/turbo_tests/runner.rb index 026d593..e28ecb6 100644 --- a/lib/turbo_tests/runner.rb +++ b/lib/turbo_tests/runner.rb @@ -10,15 +10,8 @@ class Runner using CoreExtensions def self.run(opts = {}) - files = opts[:files] - formatters = opts[:formatters] - tags = opts[:tags] - start_time = opts.fetch(:start_time) { RSpec::Core::Time.now } - runtime_log = opts.fetch(:runtime_log, nil) verbose = opts.fetch(:verbose, false) - fail_fast = opts.fetch(:fail_fast, nil) - count = opts.fetch(:count, nil) seed = opts.fetch(:seed) seed_used = !seed.nil? @@ -26,28 +19,22 @@ def self.run(opts = {}) warn "VERBOSE" end - reporter = Reporter.from_config(formatters, start_time, seed, seed_used) - new( - reporter: reporter, - files: files, - tags: tags, - runtime_log: runtime_log, + **opts, + start_time: start_time, verbose: verbose, - fail_fast: fail_fast, - count: count, seed: seed, - seed_used: seed_used, + seed_used: seed_used ).run end - def initialize(opts) - @reporter = opts[:reporter] + def initialize(**opts) + @formatters = opts[:formatters] @files = opts[:files] @tags = opts[:tags] - @runtime_log = opts[:runtime_log] || "tmp/turbo_rspec_runtime.log" @verbose = opts[:verbose] @fail_fast = opts[:fail_fast] + @start_time = opts[:start_time] @count = opts[:count] @seed = opts[:seed] @seed_used = opts[:seed_used] @@ -56,36 +43,32 @@ def initialize(opts) @load_count = 0 @failure_count = 0 + @runtime_log = opts[:runtime_log] || "tmp/turbo_rspec_runtime.log" + @parallel_options = opts.fetch(:parallel_options, {}) + @parallel_options[:runtime_log] = @runtime_log + @messages = Thread::Queue.new @threads = [] @error = false end def run + @reporter = Reporter.from_config(@formatters, @start_time, @seed, @seed_used, @files, @parallel_options) + @num_processes = [ ParallelTests.determine_number_of_processes(@count), ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size ].min - use_runtime_info = @files == ["spec"] - - group_opts = {} - - if use_runtime_info - group_opts[:runtime_log] = @runtime_log - else - group_opts[:group_by] = :filesize - end - tests_in_groups = ParallelTests::RSpec::Runner.tests_in_groups( @files, @num_processes, - **group_opts + @parallel_options ) subprocess_opts = { - record_runtime: use_runtime_info, + record_runtime: @parallel_options[:group_by] == :runtime } @reporter.report(tests_in_groups) do |reporter|