From 040fecc98894de42a433d94a15d19f07434b77f8 Mon Sep 17 00:00:00 2001 From: Phil Pirozhkov Date: Thu, 14 Jan 2021 10:01:26 +0300 Subject: [PATCH 1/2] Add testing snippets Snippet is a self-contained example that defines the configuration, Rails project code and specs to run. Snippets: - allow for clean separation between different snippets - work quite fast - reuse the already installed gems that specs and Cukes use - do not litter - do not depend on other parts of the build In theory snippets retain the ability to use generators and arbitrary commands, but it makes the case under test less evident. Co-authored-by: Benoit Tigeot --- BUILD_DETAIL.md | 15 +++++++ Changelog.md | 1 + Gemfile | 21 +--------- Gemfile-sqlite-dependencies | 20 ++++++++++ script/run_build | 2 + script/run_snippets.sh | 13 ++++++ snippets/use_active_record_false.rb | 61 +++++++++++++++++++++++++++++ 7 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 Gemfile-sqlite-dependencies create mode 100755 script/run_snippets.sh create mode 100644 snippets/use_active_record_false.rb diff --git a/BUILD_DETAIL.md b/BUILD_DETAIL.md index c2bea9ddf5..fc5b269986 100644 --- a/BUILD_DETAIL.md +++ b/BUILD_DETAIL.md @@ -66,6 +66,21 @@ $ bundle exec cucumber $ bin/cucumber ``` +## Snippets + +RSpec Rails uses snippets, self-contained examples that are used to cover +cases and regressions that don't need a full-blown example application to +reproduce. + +Snippets reuse the already installed gems, and don't attempt to install gem +versions that are not on the system already to prevent version mismatches. + +Run with: + +``` +$ script/run_snippets.sh +``` + ## YARD documentation RSpec uses [YARD](https://yardoc.org/) for API documentation on the [rspec.info site](https://rspec.info/). diff --git a/Changelog.md b/Changelog.md index 06fa41d24c..90410b3a49 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Enhancements: (Andrew W. Lee, #2372) * Improve request spec "controller" scafold when no action is specified. (Thomas Hareau, #2399) +* Introduce testing snippets concept (Phil Pirozhkov, Benoit Tigeot, #2423) Bug Fixes: diff --git a/Gemfile b/Gemfile index a438462dc1..8d74d1b894 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,4 @@ source "https://rubygems.org" -version_file = File.expand_path('.rails-version', __dir__) -RAILS_VERSION = ENV['RAILS_VERSION'] || (File.exist?(version_file) && File.read(version_file).chomp) || "" gemspec @@ -22,28 +20,11 @@ end gem 'capybara' -MAJOR = - case RAILS_VERSION - when /5-2-stable/ - 5 - when /master/, /stable/, nil, false, '' - 6 - else - /(\d+)[\.|-]\d+/.match(RAILS_VERSION).captures.first.to_i - end - -if MAJOR >= 6 - # sqlite3 is an optional, unspecified, dependency and Rails 6.0 only supports `~> 1.4` - gem 'sqlite3', '~> 1.4', platforms: [:ruby] -else - # Similarly, Rails 5.0 only supports '~> 1.3.6'. Rails 5.1-5.2 support '~> 1.3', '>= 1.3.6' - gem 'sqlite3', '~> 1.3.6', platforms: [:ruby] -end - # Until 1.13.2 is released due to Rubygems usage gem 'ffi', '~> 1.12.0' custom_gemfile = File.expand_path('Gemfile-custom', __dir__) eval_gemfile custom_gemfile if File.exist?(custom_gemfile) +eval_gemfile 'Gemfile-sqlite-dependencies' eval_gemfile 'Gemfile-rails-dependencies' diff --git a/Gemfile-sqlite-dependencies b/Gemfile-sqlite-dependencies new file mode 100644 index 0000000000..ace683988a --- /dev/null +++ b/Gemfile-sqlite-dependencies @@ -0,0 +1,20 @@ +version_file = File.expand_path('.rails-version', __dir__) +RAILS_VERSION = ENV['RAILS_VERSION'] || (File.exist?(version_file) && File.read(version_file).chomp) || "" + +MAJOR = + case RAILS_VERSION + when /5-2-stable/ + 5 + when /master/, /stable/, nil, false, '' + 6 + else + /(\d+)[\.|-]\d+/.match(RAILS_VERSION).captures.first.to_i + end + +if MAJOR >= 6 +# sqlite3 is an optional, unspecified, dependency and Rails 6.0 only supports `~> 1.4` + gem 'sqlite3', '~> 1.4', platforms: [:ruby] +else +# Similarly, Rails 5.0 only supports '~> 1.3.6'. Rails 5.1-5.2 support '~> 1.3', '>= 1.3.6' + gem 'sqlite3', '~> 1.3.6', platforms: [:ruby] +end diff --git a/script/run_build b/script/run_build index e20840e3ca..b7e542bfba 100755 --- a/script/run_build +++ b/script/run_build @@ -20,6 +20,8 @@ fi fold "cukes" run_cukes +fold "snippets" script/run_snippets.sh + if documentation_enforced; then fold "doc check" check_documentation_coverage fi diff --git a/script/run_snippets.sh b/script/run_snippets.sh new file mode 100755 index 0000000000..45146e0277 --- /dev/null +++ b/script/run_snippets.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +( + cd snippets + # This is required to load `bundle/inline` + unset RUBYOPT + for snippet in *.rb; + do + echo Running $snippet + ruby $snippet + done +) diff --git a/snippets/use_active_record_false.rb b/snippets/use_active_record_false.rb new file mode 100644 index 0000000000..2965223084 --- /dev/null +++ b/snippets/use_active_record_false.rb @@ -0,0 +1,61 @@ +if __FILE__ =~ /^snippets/ + fail "Snippets are supposed to be run from their own directory to avoid side " \ + "effects as e.g. the root `Gemfile`, or `spec/spec_helpers.rb` to be " \ + "loaded by the root `.rspec`." +end + +# We opt-out from using RubyGems, but `bundler/inline` requires it +require 'rubygems' + +require "bundler/inline" + +# We pass `false` to `gemfile` to skip the installation of gems, +# because it may install versions that would conflict with versions +# from the main `Gemfile.lock`. +gemfile(false) do + source "https://rubygems.org" + + git_source(:github) { |repo| "https://github.com/#{repo}.git" } + + # Those Gemfiles carefully pick the right versions depending on + # settings in the ENV, `.rails-version` and `maintenance-branch`. + Dir.chdir('..') do + eval_gemfile 'Gemfile-sqlite-dependencies' + # This Gemfile expects `maintenance-branch` file to be present + # in the current directory. + eval_gemfile 'Gemfile-rspec-dependencies' + # This Gemfile expects `.rails-version` file + eval_gemfile 'Gemfile-rails-dependencies' + end + + gem "rspec-rails", path: "../" +end + +# Run specs at exit +require "rspec/autorun" + +# This snippet describes the case when ActiveRecord is loaded, but +# `use_active_record` is set to `false` in RSpec configuration. + +# Initialization +require "active_record/railtie" +require "rspec/rails" + +# This connection will do for database-independent bug reports +ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") + +# RSpec configuration +RSpec.configure do |config| + config.use_active_record = false +end + +# Rails project code +class Foo +end + +# Rails project specs +RSpec.describe Foo do + it 'does not not break' do + Foo + end +end From 23c42e72004527f6561eb19be73ecf76f2f8c174 Mon Sep 17 00:00:00 2001 From: Phil Pirozhkov Date: Wed, 23 Dec 2020 20:08:55 +0300 Subject: [PATCH 2/2] Fix WrongScopeError when use_active_record = false Fixes #2417 --- Changelog.md | 1 + lib/rspec/rails/fixture_support.rb | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index 90410b3a49..8395f7743c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -26,6 +26,7 @@ Bug Fixes: (Phil Pirozhkov, Jon Rowe, #2353, #2354) * Remove old #fixture_path feature detection code which broke under newer Rails. (Koen Punt, Jon Rowe, #2370) +* Fix an error when `use_active_record` is `false` (Phil Pirozhkov, #2423) ### 4.0.1 / 2020-05-16 [Full Changelog](https://github.com/rspec/rspec-rails/compare/v4.0.0...v4.0.1) diff --git a/lib/rspec/rails/fixture_support.rb b/lib/rspec/rails/fixture_support.rb index 2161b115c6..02786d3c29 100644 --- a/lib/rspec/rails/fixture_support.rb +++ b/lib/rspec/rails/fixture_support.rb @@ -9,6 +9,13 @@ module FixtureSupport include RSpec::Rails::MinitestAssertionAdapter include ActiveRecord::TestFixtures + if ::Rails.version.to_f >= 6.1 + # @private return the example name for TestFixtures + def name + @example + end + end + included do if RSpec.configuration.use_active_record? include Fixtures @@ -50,13 +57,6 @@ def proxy_method_warning_if_called_in_before_context_scope(method_name) end end end - - if ::Rails.version.to_f >= 6.1 - # @private return the example name for TestFixtures - def name - @example - end - end end end end