From e163eb8650cb38d03829cd8aa537a3f32af3682f Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Mon, 21 Jun 2021 12:58:09 -0400 Subject: [PATCH] Enhance test suite to emit JUnit XML test reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for detecting flaky tests with BuildPulse, this commit sets up the rspec_junit_formatter gem to output JUnit XML reports of the test suite, which is the format used by BuildPulse and various other tooling that interprets test results. Because the test suite uses the parallel_tests gem, this commit incorporates some related changes to make all the parallel_tests gem and the rspec_junit_formatter gem to cooperate with each other. rspec_junit_formatter writes everything to a single XML file. That works fine when there's only one process writing to the file. By default, whatever process finishes last will write to the file and clobber the output of all the other processes that wrote to the file. 🙈 To prevent this issue, the parallel_tests wiki recommends adding a `.rspec_parallel` file to specify its RSpec options (https://github.com/grosser/parallel_tests/wiki#with-rspec_junit_formatter----by-jgarber), then the project can specify different files for each process to write to like so: --format RspecJunitFormatter --out tmp/rspec<%= ENV['TEST_ENV_NUMBER'] %>.xml However, prior to this commit, the Homebrew/brew test suite specified its RSpec options via the command line. Unfortunately though, there's no way (AFAICT) to set the equivalent of these options via the command line: --format RspecJunitFormatter --out tmp/rspec<%= ENV['TEST_ENV_NUMBER'] %>.xml So, we need to use a `.rspec_parallel` file to specify these options ☝️. However, it appears that RSpec allows you to specify formatters _either_ in an options file (like `.rspec_parallel`) _or_ via command-line args. But if you specify any formatters via command-line args, then all formatters in the options file are ignored. (I suspect that's somehow related to this bit of code in rspec-core: https://github.com/rspec/rspec-core/blob/v3.10.0/lib/rspec/core/configuration_options.rb#L64.) With that in mind, in order to have the RspecJunitFormatter configured in `.rspec_parallel`, we need to move the other formatters into `.rpsec_parallel` as well, instead of passing them as command-line args. Therefore, this commit moves all the formatters into a `.rspec_parallel` file. --- .gitignore | 2 ++ Library/Homebrew/.rspec_parallel | 6 ++++++ Library/Homebrew/Gemfile | 1 + Library/Homebrew/Gemfile.lock | 3 +++ Library/Homebrew/dev-cmd/tests.rb | 6 +----- 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 Library/Homebrew/.rspec_parallel diff --git a/.gitignore b/.gitignore index 9274f245c7..6001fe1574 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ /Library/Homebrew/test/.gem /Library/Homebrew/test/.subversion /Library/Homebrew/test/coverage +/Library/Homebrew/test/junit /Library/Homebrew/test/fs_leak_log /Library/Homebrew/vendor/portable-ruby /Library/Taps @@ -133,6 +134,7 @@ **/vendor/bundle/ruby/*/gems/rspec-*/ **/vendor/bundle/ruby/*/gems/rspec-core-*/ **/vendor/bundle/ruby/*/gems/rspec-expectations-*/ +**/vendor/bundle/ruby/*/gems/rspec_junit_formatter-*/ **/vendor/bundle/ruby/*/gems/rspec-its-*/ **/vendor/bundle/ruby/*/gems/rspec-mocks-*/ **/vendor/bundle/ruby/*/gems/rspec-retry-*/ diff --git a/Library/Homebrew/.rspec_parallel b/Library/Homebrew/.rspec_parallel new file mode 100644 index 0000000000..5200a0136d --- /dev/null +++ b/Library/Homebrew/.rspec_parallel @@ -0,0 +1,6 @@ +--format NoSeedProgressFormatter +--format ParallelTests::RSpec::RuntimeLogger +--out <%= ENV["PARALLEL_RSPEC_LOG_PATH"] %> +--format RspecJunitFormatter +--out test/junit/rspec<%= ENV["TEST_ENV_NUMBER"] %>.xml +<%= "--format RSpec::Github::Formatter" if ENV["GITHUB_ACTIONS"] %> diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 70c9b44ba2..7ff09f5ea3 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -12,6 +12,7 @@ gem "ronn", require: false gem "rspec", require: false gem "rspec-github", require: false gem "rspec-its", require: false +gem "rspec_junit_formatter", require: false gem "rspec-retry", require: false gem "rspec-wait", require: false gem "rubocop", require: false diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock index f3e24eedad..96f9dc30f8 100644 --- a/Library/Homebrew/Gemfile.lock +++ b/Library/Homebrew/Gemfile.lock @@ -109,6 +109,8 @@ GEM rspec-support (3.10.2) rspec-wait (0.0.9) rspec (>= 3, < 4) + rspec_junit_formatter (0.4.1) + rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.17.0) parallel (~> 1.10) parser (>= 3.0.0.0) @@ -194,6 +196,7 @@ DEPENDENCIES rspec-retry rspec-sorbet rspec-wait + rspec_junit_formatter rubocop rubocop-ast rubocop-performance diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index f35117e56e..57e0223a56 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -111,6 +111,7 @@ module Homebrew else "#{HOMEBREW_CACHE}/#{parallel_rspec_log_name}" end + ENV["PARALLEL_RSPEC_LOG_PATH"] = parallel_rspec_log_path parallel_args = if ENV["CI"] %W[ @@ -133,13 +134,8 @@ module Homebrew --seed #{seed} --color --require spec_helper - --format NoSeedProgressFormatter - --format ParallelTests::RSpec::RuntimeLogger - --out #{parallel_rspec_log_path} ] - bundle_args << "--format" << "RSpec::Github::Formatter" if ENV["GITHUB_ACTIONS"] - unless OS.mac? bundle_args << "--tag" << "~needs_macos" << "--tag" << "~cask" files = files.reject { |p| p =~ %r{^test/(os/mac|cask)(/.*|_spec\.rb)$} }