From 040fecc98894de42a433d94a15d19f07434b77f8 Mon Sep 17 00:00:00 2001 From: Phil Pirozhkov Date: Thu, 14 Jan 2021 10:01:26 +0300 Subject: [PATCH] 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